package org.icepdf.core.pobjects;
import org.icepdf.core.pobjects.security.SecurityManager;
import org.icepdf.core.util.Library;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
/**
* If a PDF file contains file specifications that refer to an external file and the PDF file is archived or
* transmitted, some provision should be made to ensure that the external references will remain valid. One way to
* do this is to arrange for copies of the external files to accompany the PDF file. Embedded file streams (PDF 1.3)
* address this problem by allowing the contents of referenced files to be embedded directly within the body of the
* PDF file. This makes the PDF file a self-contained unit that can be stored or transmitted as a single entity.
*
* @since 6.2
*/
public class EmbeddedFileStream extends Dictionary {
/**
* An embedded file parameter dictionary that shall contain additional file-specific information.
*/
public static final Name PARAMS_KEY = new Name("Params");
/**
* The size of the uncompressed embedded file, in bytes.
*/
public static final Name PARAMS_SIZE_KEY = new Name("Size");
/**
* The date and time when the embedded file was created.
*/
public static final Name PARAMS_CREATION_DATE_KEY = new Name("CreationDate");
/**
* The date and time when the embedded file was last modified.
*/
public static final Name PARAMS_MOD_DATE_KEY = new Name("ModDate");
/**
* A sub dictionary containing additional information specific to Mac OS files (see Table 47).
*/
public static final Name PARAMS_MAC_KEY = new Name("Mac");
/**
* The embedded file’s file type. It shall be encoded as an integer according to Mac OS conventions: a 4-character
* ASCII text literal, that shall be a 32-bit integer, with the high-order byte first.
*/
public static final Name PARAMS_MAC_SUBTYPE_KEY = new Name("Subtype");
/**
* The embedded file’s creator signature shall be encoded in the same way as Subtype.
*/
public static final Name PARAMS_MAC_CREATOR_KEY = new Name("Creator");
/**
* the binary contents of the embedded file’s resource fork.
*/
public static final Name PARAMS_MAC_RES_FORK_KEY = new Name("ResFork");
/**
* A 16-byte string that is the checksum of the bytes of the uncompressed embedded file. The checksum shall be
* calculated by applying the standard MD5 message-digest algorithm (described in Internet RFC 1321, The MD5
* Message-Digest Algorithm; see the Bibliography) to the bytes of the embedded file stream.
*/
public static final Name PARAMS_CHECK_SUM_KEY = new Name("CheckSum");
protected Stream fileStream;
private SecurityManager securityManager;
public EmbeddedFileStream(Library library, Stream fileStream) {
super(library, fileStream.getEntries());
this.securityManager = library.getSecurityManager();
this.fileStream = fileStream;
}
/**
* (Optional) The type of PDF object that this dictionary describes; if present, shall be EmbeddedFile for an
* embedded file stream.
*
* @return type value if present otherwise null.
*/
public Name getType() {
return library.getName(entries, TYPE_KEY);
}
/**
* (Optional) The subtype of the embedded file. The value of this entry shall be a first-class name, as defined in
* Annex E. Names without a registered prefix shall conform to the MIME media type names defined in
* Internet RFC 2046, Multipurpose Internet Mail Extensions (MIME), Part Two: Media Types (see the Bibliography),
* with the provision that characters not allowed in names shall use the 2-character hexadecimal code format
* described in 7.3.5, "Name Objects."
*
* @return mime media type of object
*/
public Name getSubType() {
return library.getName(entries, SUBTYPE_KEY);
}
/**
* An embedded file parameter dictionary that shall contain additional file-specific information.
*
* @return the raw dictionary.
*/
public HashMap getParams() {
return library.getDictionary(entries, PARAMS_KEY);
}
/**
* (Optional) The size of the uncompressed embedded file, in bytes.
*
* @return uncompressed size in bytes, null if not specified.
*/
public int getParamUncompressedSize() {
int size = library.getInt(getParams(), PARAMS_SIZE_KEY);
if (size == 0){
size = fileStream.getDecodedStreamBytes().length;
}
return size;
}
/**
* Get compressed size in bytes.
*
* @return
*/
public int getCompressedSize() {
return fileStream.getRawBytes().length;
}
/**
* Gets the file streams decoded data stream which can be used to open or save the file given the appropriate
* file handler.
*
* @return decoded byte array input stream.
* @throws IOException io exception during stream decoding.
*/
public InputStream getDecodedStreamData() throws IOException {
return fileStream.getDecodedByteArrayInputStream();
}
/**
* (Optional) The date and time when the embedded file was created.
*
* @return creation date if set, null otherwise.
*/
public PDate getParamCreationData() {
Object value = library.getObject(getParams(), PARAMS_CREATION_DATE_KEY);
if (value != null && value instanceof StringObject) {
StringObject text = (StringObject) value;
return new PDate(securityManager, text.getDecryptedLiteralString(securityManager));
}
return null;
}
/**
* (Optional) The date and time when the embedded file was created.
*
* @return creation date if set, null otherwise.
*/
public PDate getParamLastModifiedData() {
Object value = library.getObject(getParams(), PARAMS_MOD_DATE_KEY);
if (value != null && value instanceof StringObject) {
StringObject text = (StringObject) value;
return new PDate(securityManager, text.getDecryptedLiteralString(securityManager));
}
return null;
}
/**
* (Optional) A sub dictionary containing additional information specific to Mac OS files
*
* @return mac sub dictionary, or null if not set.
*/
public HashMap getMacDictionary() {
return library.getDictionary(getParams(), PARAMS_MAC_KEY);
}
/**
* (Optional) A 16-byte string that is the checksum of the bytes of the uncompressed embedded file. The checksum
* shall be calculated by applying the standard MD5 message-digest algorithm (described in Internet RFC 1321,
* The MD5 Message-Digest Algorithm; see the Bibliography) to the bytes of the embedded file stream.
*
* @return checksum or null;
*/
public String getCheckSum() {
Object value = library.getObject(getParams(), PARAMS_CHECK_SUM_KEY);
if (value != null && value instanceof StringObject) {
StringObject text = (StringObject) value;
return text.getDecryptedLiteralString(securityManager);
}
return null;
}
}