You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2024/05/09 10:54:36 UTC
svn commit: r1917610 - in /pdfbox/trunk/pdfbox/src: main/java/org/apache/pdfbox/cos/ main/java/org/apache/pdfbox/pdfparser/ main/java/org/apache/pdfbox/pdfwriter/ main/java/org/apache/pdfbox/pdmodel/encryption/ main/java/org/apache/pdfbox/pdmodel/inter...
Author: lehmi
Date: Thu May 9 10:54:36 2024
New Revision: 1917610
URL: http://svn.apache.org/viewvc?rev=1917610&view=rev
Log:
PDFBOX-5469: make COSString immutable
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/cos/TestCOSString.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java?rev=1917610&r1=1917609&r2=1917610&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java Thu May 9 10:54:36 2024
@@ -47,8 +47,8 @@ public final class COSString extends COS
{
private static final Logger LOG = LogManager.getLogger(COSString.class);
- private byte[] bytes;
- private boolean forceHexForm;
+ private final byte[] bytes;
+ private final boolean forceHexForm;
// legacy behaviour for old PDFParser
public static final boolean FORCE_PARSING =
@@ -62,7 +62,21 @@ public final class COSString extends COS
*/
public COSString(byte[] bytes)
{
- setValue(bytes);
+ this(bytes, false);
+ }
+
+ /**
+ * Creates a new PDF string from a byte array. This method can be used to read a string from an existing PDF file,
+ * or to create a new byte string.
+ *
+ * @param bytes The raw bytes of the PDF text string or byte string.
+ * @param forceHex forces the hexadecimal presentation of the string if set to true
+ *
+ */
+ public COSString(byte[] bytes, boolean forceHex)
+ {
+ forceHexForm = forceHex;
+ this.bytes = Arrays.copyOf(bytes, bytes.length);
}
/**
@@ -72,6 +86,19 @@ public final class COSString extends COS
*/
public COSString(String text)
{
+ this(text, false);
+ }
+
+ /**
+ * Creates a new <i>text string</i> from a Java String.
+ *
+ * @param text The string value of the object.
+ * @param forceHex forces the hexadecimal presentation of the string if set to true
+ *
+ */
+ public COSString(String text, boolean forceHex)
+ {
+ forceHexForm = forceHex;
// check whether the string uses only characters available in PDFDocEncoding
boolean isOnlyPDFDocEncoding = true;
for (char c : text.toCharArray())
@@ -142,30 +169,6 @@ public final class COSString extends COS
}
/**
- * Sets the raw value of this string.
- *
- * @param value The raw bytes of the PDF text string or byte string.
- *
- * @deprecated to be removed in a future release.
- */
- @Deprecated
- public void setValue(byte[] value)
- {
- bytes = value.clone();
- }
-
- /**
- * Sets whether to force the string is to be written in hex form.
- * This is needed when signing PDF files.
- *
- * @param value True to force hex.
- */
- public void setForceHexForm(boolean value)
- {
- this.forceHexForm = value;
- }
-
- /**
* Returns true if the string is to be written in hex form.
*
* @return true if the COSString is written in hex form
@@ -219,7 +222,7 @@ public final class COSString extends COS
*/
public byte[] getBytes()
{
- return bytes.clone();
+ return Arrays.copyOf(bytes, bytes.length);
}
/**
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java?rev=1917610&r1=1917609&r2=1917610&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java Thu May 9 10:54:36 2024
@@ -588,7 +588,9 @@ public class COSParser extends BaseParse
}
else if (securityHandler != null)
{
- securityHandler.decrypt(parsedObject, objKey.getNumber(), objKey.getGeneration());
+ parsedObject = securityHandler.decrypt(parsedObject, objKey.getNumber(),
+ objKey.getGeneration());
+ parsedObject.setKey(objKey);
}
if (!endObjectKey.startsWith(ENDOBJ_STRING))
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java?rev=1917610&r1=1917609&r2=1917610&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java Thu May 9 10:54:36 2024
@@ -1429,12 +1429,17 @@ public class COSWriter implements ICOSVi
{
if (willEncrypt)
{
- pdDocument.getEncryption().getSecurityHandler().encryptString(
+ COSString encryptedCOSString = (COSString) pdDocument.getEncryption()
+ .getSecurityHandler().encryptString(
obj,
currentObjectKey.getNumber(),
currentObjectKey.getGeneration());
+ COSWriter.writeString(encryptedCOSString, getStandardOutput());
+ }
+ else
+ {
+ COSWriter.writeString(obj, getStandardOutput());
}
- COSWriter.writeString(obj, getStandardOutput());
}
/**
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java?rev=1917610&r1=1917609&r2=1917610&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java Thu May 9 10:54:36 2024
@@ -444,29 +444,33 @@ public abstract class SecurityHandler<T_
/**
* This will dispatch to the correct method.
*
- * @param obj The object to decrypt.
+ * @param obj The object to decrypt.
* @param objNum The object number.
* @param genNum The object generation Number.
+ *
+ * @return the encrypted/decrypted COS object
*
* @throws IOException If there is an error getting the stream data.
*/
- public void decrypt(COSBase obj, long objNum, long genNum) throws IOException
+ public COSBase decrypt(COSBase obj, long objNum, long genNum) throws IOException
{
// PDFBOX-4477: only cache strings and streams, this improves speed and memory footprint
if (obj instanceof COSString)
{
if (objects.contains(obj))
{
- return;
+ return obj;
}
- objects.add(obj);
- decryptString((COSString) obj, objNum, genNum);
+ // replace the given COSString object with the encrypted/decrypted version
+ COSBase decryptedString = decryptString((COSString) obj, objNum, genNum);
+ objects.add(decryptedString);
+ return decryptedString;
}
- else if (obj instanceof COSStream)
+ if (obj instanceof COSStream)
{
if (objects.contains(obj))
{
- return;
+ return obj;
}
objects.add(obj);
decryptStream((COSStream) obj, objNum, genNum);
@@ -479,6 +483,7 @@ public abstract class SecurityHandler<T_
{
decryptArray((COSArray) obj, objNum, genNum);
}
+ return obj;
}
/**
@@ -610,7 +615,7 @@ public abstract class SecurityHandler<T_
// within a dictionary only the following kind of COS objects have to be decrypted
if (value instanceof COSString || value instanceof COSArray || value instanceof COSDictionary)
{
- decrypt(value, objNum, genNum);
+ entry.setValue(decrypt(value, objNum, genNum));
}
}
}
@@ -621,14 +626,15 @@ public abstract class SecurityHandler<T_
* @param string the string to decrypt.
* @param objNum The object number.
* @param genNum The object generation number.
- *
+ *
+ * @return the decrypted COSString
*/
- private void decryptString(COSString string, long objNum, long genNum)
+ private COSBase decryptString(COSString string, long objNum, long genNum)
{
// String encrypted with identity filter
if (COSName.IDENTITY.equals(stringFilterName))
{
- return;
+ return string;
}
ByteArrayInputStream data = new ByteArrayInputStream(string.getBytes());
@@ -636,12 +642,13 @@ public abstract class SecurityHandler<T_
try
{
encryptData(objNum, genNum, data, outputStream, true /* decrypt */);
- string.setValue(outputStream.toByteArray());
+ return new COSString(outputStream.toByteArray());
}
catch (IOException ex)
{
LOG.error("Failed to decrypt COSString of length {} in object {}: {}",
string.getBytes().length, objNum, ex.getMessage(), ex);
+ return string;
}
}
@@ -652,14 +659,16 @@ public abstract class SecurityHandler<T_
* @param objNum The object number.
* @param genNum The object generation number.
*
+ * @return the encrypted COSString
+ *
* @throws IOException If an error occurs writing the new string.
*/
- public void encryptString(COSString string, long objNum, int genNum) throws IOException
+ public COSBase encryptString(COSString string, long objNum, int genNum) throws IOException
{
ByteArrayInputStream data = new ByteArrayInputStream(string.getBytes());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
encryptData(objNum, genNum, data, buffer, false /* encrypt */);
- string.setValue(buffer.toByteArray());
+ return new COSString(buffer.toByteArray());
}
/**
@@ -675,7 +684,7 @@ public abstract class SecurityHandler<T_
{
for (int i = 0; i < array.size(); i++)
{
- decrypt(array.get(i), objNum, genNum);
+ array.set(i, decrypt(array.get(i), objNum, genNum));
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java?rev=1917610&r1=1917609&r2=1917610&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java Thu May 9 10:54:36 2024
@@ -394,8 +394,7 @@ public class PDSignature implements COSO
*/
public void setContents(byte[] bytes)
{
- COSString string = new COSString(bytes);
- string.setForceHexForm(true);
+ COSString string = new COSString(bytes, true);
dictionary.setItem(COSName.CONTENTS, string);
}
Modified: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/cos/TestCOSString.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/cos/TestCOSString.java?rev=1917610&r1=1917609&r2=1917610&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/cos/TestCOSString.java (original)
+++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/cos/TestCOSString.java Thu May 9 10:54:36 2024
@@ -59,15 +59,14 @@ class TestCOSString extends TestCOSBase
{
String inputString = "Test with a text and a few numbers 1, 2 and 3";
String pdfHex = "<" + createHex(inputString) + ">";
- COSString cosStr = new COSString(inputString);
- cosStr.setForceHexForm(true);
+ COSString cosStr = new COSString(inputString, true);
writePDFTests(pdfHex, cosStr);
COSString escStr = new COSString(ESC_CHAR_STRING);
writePDFTests("(" + ESC_CHAR_STRING_PDF_FORMAT + ")", escStr);
- escStr.setForceHexForm(true);
+ COSString escStrHex = new COSString(ESC_CHAR_STRING, true);
// Escape characters not escaped in hex version
- writePDFTests("<" + createHex(ESC_CHAR_STRING) + ">", escStr);
+ writePDFTests("<" + createHex(ESC_CHAR_STRING) + ">", escStrHex);
}
/**
@@ -265,8 +264,8 @@ class TestCOSString extends TestCOSBase
testSubj.accept(visitor);
assertEquals("(" + ESC_CHAR_STRING_PDF_FORMAT + ")", outStream.toString());
outStream.reset();
- testSubj.setForceHexForm(true);
- testSubj.accept(visitor);
+ COSString testSubjHex = new COSString(ESC_CHAR_STRING, true);
+ testSubjHex.accept(visitor);
assertEquals("<" + createHex(ESC_CHAR_STRING) + ">", outStream.toString());
}
@@ -287,8 +286,7 @@ class TestCOSString extends TestCOSBase
COSString y1 = new COSString("Test");
assertEquals(x1, y1);
assertEquals(y1, x1);
- COSString x2 = new COSString("Test");
- x2.setForceHexForm(true);
+ COSString x2 = new COSString("Test", true);
// also if x != y then y != x
assertNotEquals(x1, x2);
assertNotEquals(x2, x1);
@@ -316,8 +314,8 @@ class TestCOSString extends TestCOSBase
assertNotEquals(str1.hashCode(), str2.hashCode());
COSString str3 = new COSString("Test1");
assertEquals(str1.hashCode(), str3.hashCode());
- str3.setForceHexForm(true);
- assertNotEquals(str1.hashCode(), str3.hashCode());
+ COSString str3Hex = new COSString("Test1", true);
+ assertNotEquals(str1.hashCode(), str3Hex.hashCode());
}
/**