Skip to content

Commit 680b4fb

Browse files
Support encrypted PDFs - Resolves #11
1 parent 4a9c368 commit 680b4fb

4 files changed

Lines changed: 87 additions & 3 deletions

File tree

Binary file not shown.

pdf2htmlEX/src/androidTest/java/com/viliussutkus89/android/pdf2htmlex/InstrumentedTests.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.io.InputStream;
3737
import java.io.OutputStream;
3838

39+
import static org.junit.Assert.assertNull;
3940
import static org.junit.Assert.assertTrue;
4041
import static org.junit.Assert.fail;
4142

@@ -104,4 +105,57 @@ public void conversionTwiceTest() throws IOException {
104105
conversionTest();
105106
}
106107

108+
@Test
109+
public synchronized void encryptedPdfTest() throws IOException {
110+
pdf2htmlEX converter = new pdf2htmlEX(InstrumentationRegistry.getInstrumentation().getTargetContext());
111+
112+
// encrypted_fontfile3_opentype.pdf generated using:
113+
// qpdf --encrypt sample-user-password sample-owner-password 256 -- fontfile3_opentype.pdf encrypted_fontfile3_opentype.pdf
114+
File pdfFile = extractAssetPDF("encrypted_fontfile3_opentype.pdf");
115+
File htmlFile;
116+
try {
117+
htmlFile = converter.setInputPDF(pdfFile)
118+
.setOwnerPassword("sample-owner-password")
119+
.setUserPassword("sample-user-password")
120+
.convert();
121+
} catch (IOException | pdf2htmlEX.ConversionFailedException e) {
122+
pdfFile.delete();
123+
e.printStackTrace();
124+
fail("Failed to convert PDF to HTML");
125+
return;
126+
}
127+
128+
pdfFile.delete();
129+
130+
assertTrue("Converted HTML file not found!", htmlFile.exists());
131+
assertTrue("Converted HTML file empty!", htmlFile.length() > 0);
132+
133+
htmlFile.delete();
134+
}
135+
136+
@Test
137+
public synchronized void encryptedPdfWrongPasswordTest() throws IOException {
138+
pdf2htmlEX converter = new pdf2htmlEX(InstrumentationRegistry.getInstrumentation().getTargetContext());
139+
140+
// encrypted_fontfile3_opentype.pdf generated using:
141+
// qpdf --encrypt sample-user-password sample-owner-password 256 -- fontfile3_opentype.pdf encrypted_fontfile3_opentype.pdf
142+
File pdfFile = extractAssetPDF("encrypted_fontfile3_opentype.pdf");
143+
File htmlFile = null;
144+
try {
145+
htmlFile = converter.setInputPDF(pdfFile)
146+
.setOwnerPassword("wrong-owner-password")
147+
.setUserPassword("wrong-user-password")
148+
.convert();
149+
} catch (pdf2htmlEX.ConversionFailedException ignored) {
150+
} catch (IOException e) {
151+
pdfFile.delete();
152+
e.printStackTrace();
153+
fail("Failed to convert PDF to HTML");
154+
return;
155+
}
156+
pdfFile.delete();
157+
158+
assertNull("Conversion succeeded when it should have failed because of wrong encryption password!", htmlFile);
159+
}
160+
107161
}

pdf2htmlEX/src/main/cpp/pdf2htmlEX.cc

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class CCharGC {
4242
return this->cstr;
4343
}
4444

45+
bool isEmpty() const { return this->cstr[0] == '\0'; }
46+
4547
~CCharGC() {
4648
env->ReleaseStringUTFChars(this->input, this->cstr);
4749
}
@@ -88,12 +90,16 @@ Java_com_viliussutkus89_android_pdf2htmlex_pdf2htmlEX_call_1pdf2htmlEX(JNIEnv *e
8890
jstring dataDir_,
8991
jstring popplerDir_, jstring tmpDir_,
9092
jstring inputFile_,
91-
jstring outputFile_) {
93+
jstring outputFile_,
94+
jstring ownerPassword_,
95+
jstring userPassword_) {
9296
CCharGC dataDir(env, dataDir_);
9397
CCharGC popplerDir(env, popplerDir_);
9498
CCharGC tmpDir(env, tmpDir_);
9599
CCharGC inputFile(env, inputFile_);
96100
CCharGC outputFile(env, outputFile_);
101+
CCharGC ownerPassword(env, ownerPassword_);
102+
CCharGC userPassword(env, userPassword_);
97103

98104
std::vector<const std::string> args = {
99105
"libpdf2htmlEX",
@@ -103,6 +109,16 @@ Java_com_viliussutkus89_android_pdf2htmlex_pdf2htmlEX_call_1pdf2htmlEX(JNIEnv *e
103109
inputFile.c_str(), outputFile.c_str()
104110
};
105111

112+
if (!ownerPassword.isEmpty()) {
113+
args.push_back("--owner-password");
114+
args.push_back(ownerPassword.c_str());
115+
}
116+
117+
if (!userPassword.isEmpty()) {
118+
args.push_back("--user-password");
119+
args.push_back(userPassword.c_str());
120+
}
121+
106122
int argc;
107123
char **argv;
108124
int retVal = -1;

pdf2htmlEX/src/main/java/com/viliussutkus89/android/pdf2htmlex/pdf2htmlEX.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public final class pdf2htmlEX {
4040
private File m_outputHtmlsDir;
4141

4242
private File p_inputPDF;
43+
private String p_ownerPassword = "";
44+
private String p_userPassword = "";
4345

4446
public static class ConversionFailedException extends Exception {
4547
public ConversionFailedException(String errorMessage) {
@@ -98,6 +100,16 @@ public File convert(@NonNull File inputPDF) throws IOException, ConversionFailed
98100
return convert();
99101
}
100102

103+
public pdf2htmlEX setOwnerPassword(@NonNull String ownerPassword) {
104+
this.p_ownerPassword = ownerPassword;
105+
return this;
106+
}
107+
108+
public pdf2htmlEX setUserPassword(@NonNull String userPassword) {
109+
this.p_userPassword = userPassword;
110+
return this;
111+
}
112+
101113
public File convert() throws IOException, ConversionFailedException {
102114
if (null == this.p_inputPDF) {
103115
throw new ConversionFailedException("No Input PDF given!");
@@ -119,7 +131,9 @@ public File convert() throws IOException, ConversionFailedException {
119131

120132
Integer retVal = call_pdf2htmlEX(m_pdf2htmlEX_dataDir.getAbsolutePath(),
121133
m_poppler_dataDir.getAbsolutePath(), m_pdf2htmlEX_tmpDir.getAbsolutePath(),
122-
this.p_inputPDF.getAbsolutePath(), outputHtml.getAbsolutePath());
134+
this.p_inputPDF.getAbsolutePath(), outputHtml.getAbsolutePath(),
135+
this.p_ownerPassword, this.p_userPassword
136+
);
123137

124138
if (0 != retVal) {
125139
outputHtml.delete();
@@ -129,7 +143,7 @@ public File convert() throws IOException, ConversionFailedException {
129143
return outputHtml;
130144
}
131145

132-
private native int call_pdf2htmlEX(String dataDir, String popplerDir, String tmpDir, String inputFile, String outputFile);
146+
private native int call_pdf2htmlEX(String dataDir, String popplerDir, String tmpDir, String inputFile, String outputFile, String ownerPassword, String userPassword);
133147

134148
// Because Java cannot setenv for the current process
135149
static native void set_environment_value(String key, String value);

0 commit comments

Comments
 (0)