mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2025-02-18 18:02:51 +01:00
Implement pdfioFileSetPermissions.
This commit is contained in:
parent
37e80d67b1
commit
61a7964d90
@ -13,8 +13,7 @@ goals of PDFio are:
|
|||||||
|
|
||||||
- Read and write any version of PDF file
|
- Read and write any version of PDF file
|
||||||
- Provide access to pages, objects, and streams within a PDF file
|
- Provide access to pages, objects, and streams within a PDF file
|
||||||
- Support reading encrypted PDF files
|
- Support reading of encrypted PDF files
|
||||||
- Support writing PDF files with digital signatures
|
|
||||||
- Extract or embed useful metadata (author, creator, page information, etc.)
|
- Extract or embed useful metadata (author, creator, page information, etc.)
|
||||||
- "Filter" PDF files, for example to extract a range of pages or to embed fonts
|
- "Filter" PDF files, for example to extract a range of pages or to embed fonts
|
||||||
that are missing from a PDF
|
that are missing from a PDF
|
||||||
|
@ -389,7 +389,7 @@ pdfioArrayGetBinary(
|
|||||||
size_t n, // I - Index
|
size_t n, // I - Index
|
||||||
size_t *length) // O - Length of string
|
size_t *length) // O - Length of string
|
||||||
{
|
{
|
||||||
if (!a || n >= a->num_values || a->values[n].type != PDFIO_VALTYPE_BINARY || !length)
|
if (!a || n >= a->num_values || a->values[n].type != PDFIO_VALTYPE_BINARY)
|
||||||
{
|
{
|
||||||
if (length)
|
if (length)
|
||||||
*length = 0;
|
*length = 0;
|
||||||
@ -398,7 +398,9 @@ pdfioArrayGetBinary(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*length = a->values[n].value.binary.datalen;
|
if (length)
|
||||||
|
*length = a->values[n].value.binary.datalen;
|
||||||
|
|
||||||
return (a->values[n].value.binary.data);
|
return (a->values[n].value.binary.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
220
pdfio-file.c
220
pdfio-file.c
@ -1034,13 +1034,219 @@ pdfioFileSetKeywords(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'pdfioFileSetPermissions()' - Set the PDF permissions, encryption mode, and passwords.
|
||||||
|
//
|
||||||
|
// This function sets the PDF usage permissions, encryption mode, and
|
||||||
|
// passwords.
|
||||||
|
//
|
||||||
|
// > *Note*: This function must be called before creating or copying any
|
||||||
|
// > objects. Due to fundamental limitations in the PDF format, PDF encryption
|
||||||
|
// > offers little protection from disclosure. Permissions are not enforced in
|
||||||
|
// > any meaningful way.
|
||||||
|
//
|
||||||
|
|
||||||
|
bool // O - `true` on success, `false` otherwise
|
||||||
|
pdfioFileSetPermissions(
|
||||||
|
pdfio_file_t *pdf, // I - PDF file
|
||||||
|
pdfio_permission_t permissions, // I - Use permissions
|
||||||
|
pdfio_encryption_t encryption, // I - Type of encryption to use
|
||||||
|
const char *owner_password, // I - Owner password, if any
|
||||||
|
const char *user_password) // I - User password, if any
|
||||||
|
{
|
||||||
|
pdfio_dict_t *dict; // Encryption dictionary
|
||||||
|
size_t i, j; // Looping vars
|
||||||
|
_pdfio_md5_t md5; // MD5 context
|
||||||
|
uint8_t digest[16]; // 128-bit MD5 digest
|
||||||
|
_pdfio_rc4_t rc4; // RC4 encryption context
|
||||||
|
size_t len; // Length of password
|
||||||
|
uint8_t owner_pad[32], // Padded owner password
|
||||||
|
user_pad[32], // Padded user password
|
||||||
|
perm_bytes[4], // Permissions bytes
|
||||||
|
*file_id; // File ID bytes
|
||||||
|
size_t file_id_len; // Length of file ID
|
||||||
|
static uint8_t pad[32] = // Padding for passwords
|
||||||
|
{
|
||||||
|
0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
|
||||||
|
0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
|
||||||
|
0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
|
||||||
|
0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (!pdf)
|
||||||
|
return (false);
|
||||||
|
|
||||||
|
if (pdf->num_objs > 0)
|
||||||
|
{
|
||||||
|
_pdfioFileError(pdf, "You must call pdfioFileSetPermissions before adding any objects.");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encryption == PDFIO_ENCRYPTION_NONE)
|
||||||
|
return (true);
|
||||||
|
|
||||||
|
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||||
|
{
|
||||||
|
_pdfioFileError(pdf, "Unable to create encryption dictionary.");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
pdfioDictSetName(dict, "Filter", "Standard");
|
||||||
|
|
||||||
|
switch (encryption)
|
||||||
|
{
|
||||||
|
case PDFIO_ENCRYPTION_RC4_128 :
|
||||||
|
case PDFIO_ENCRYPTION_AES_128 :
|
||||||
|
// Create the 128-bit encryption keys...
|
||||||
|
if (user_password)
|
||||||
|
{
|
||||||
|
// Copy the user password and pad it with the special PDF pad bytes
|
||||||
|
if ((len = strlen(user_password)) > sizeof(user_pad))
|
||||||
|
len = sizeof(user_pad);
|
||||||
|
|
||||||
|
if (len > 0)
|
||||||
|
memcpy(user_pad, user_password, len);
|
||||||
|
if (len < sizeof(user_pad))
|
||||||
|
memcpy(user_pad + len, pad, sizeof(user_pad) - len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use default (pad) password
|
||||||
|
memcpy(user_pad, pad, sizeof(user_pad));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (owner_password && *owner_password)
|
||||||
|
{
|
||||||
|
// Copy the owner password and pad it with the special PDF pad bytes
|
||||||
|
if ((len = strlen(owner_password)) > sizeof(owner_pad))
|
||||||
|
len = sizeof(owner_pad);
|
||||||
|
|
||||||
|
if (len > 0)
|
||||||
|
memcpy(owner_pad, owner_password, len);
|
||||||
|
if (len < sizeof(owner_pad))
|
||||||
|
memcpy(owner_pad + len, pad, sizeof(owner_pad) - len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Generate a random owner password...
|
||||||
|
_pdfioCryptoMakeRandom(owner_pad, sizeof(owner_pad));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the owner key...
|
||||||
|
_pdfioCryptoMD5Init(&md5);
|
||||||
|
_pdfioCryptoMD5Append(&md5, owner_pad, 32);
|
||||||
|
_pdfioCryptoMD5Finish(&md5, digest);
|
||||||
|
|
||||||
|
// MD5 the result 50 more times...
|
||||||
|
for (i = 0; i < 50; i ++)
|
||||||
|
{
|
||||||
|
_pdfioCryptoMD5Init(&md5);
|
||||||
|
_pdfioCryptoMD5Append(&md5, digest, 16);
|
||||||
|
_pdfioCryptoMD5Finish(&md5, digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the padded user password...
|
||||||
|
memcpy(pdf->owner_key, user_pad, sizeof(pdf->owner_key));
|
||||||
|
|
||||||
|
// Encrypt the result 20 times...
|
||||||
|
for (i = 0; i < 20; i ++)
|
||||||
|
{
|
||||||
|
uint8_t encrypt_key[16];// RC4 encryption key
|
||||||
|
|
||||||
|
// XOR each byte in the digest with the loop counter to make a key...
|
||||||
|
for (j = 0; j < sizeof(encrypt_key); j ++)
|
||||||
|
encrypt_key[j] = (uint8_t)(digest[j] ^ i);
|
||||||
|
|
||||||
|
_pdfioCryptoRC4Init(&rc4, encrypt_key, sizeof(encrypt_key));
|
||||||
|
_pdfioCryptoRC4Crypt(&rc4, pdf->owner_key, sizeof(pdf->owner_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the encryption key
|
||||||
|
perm_bytes[0] = (uint8_t)permissions;
|
||||||
|
perm_bytes[1] = (uint8_t)(permissions >> 8);
|
||||||
|
perm_bytes[2] = (uint8_t)(permissions >> 16);
|
||||||
|
perm_bytes[3] = (uint8_t)(permissions >> 24);
|
||||||
|
|
||||||
|
file_id = pdfioArrayGetBinary(pdf->id_array, 0, &file_id_len);
|
||||||
|
|
||||||
|
_pdfioCryptoMD5Init(&md5);
|
||||||
|
_pdfioCryptoMD5Append(&md5, user_pad, 32);
|
||||||
|
_pdfioCryptoMD5Append(&md5, pdf->owner_key, 32);
|
||||||
|
|
||||||
|
_pdfioCryptoMD5Append(&md5, perm_bytes, 4);
|
||||||
|
_pdfioCryptoMD5Append(&md5, file_id, file_id_len);
|
||||||
|
_pdfioCryptoMD5Finish(&md5, digest);
|
||||||
|
|
||||||
|
// MD5 the result 50 times..
|
||||||
|
for (i = 0; i < 50; i ++)
|
||||||
|
{
|
||||||
|
_pdfioCryptoMD5Init(&md5);
|
||||||
|
_pdfioCryptoMD5Append(&md5, digest, 16);
|
||||||
|
_pdfioCryptoMD5Finish(&md5, digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pdf->encryption_key, digest, 16);
|
||||||
|
|
||||||
|
// Generate the user key...
|
||||||
|
_pdfioCryptoMD5Init(&md5);
|
||||||
|
_pdfioCryptoMD5Append(&md5, pad, 32);
|
||||||
|
_pdfioCryptoMD5Append(&md5, file_id, file_id_len);
|
||||||
|
_pdfioCryptoMD5Finish(&md5, pdf->user_key);
|
||||||
|
|
||||||
|
memset(pdf->user_key + 16, 0, 16);
|
||||||
|
|
||||||
|
// Encrypt the result 20 times...
|
||||||
|
for (i = 0; i < 20; i ++)
|
||||||
|
{
|
||||||
|
// XOR each byte in the key with the loop counter...
|
||||||
|
for (j = 0; j < 16; j ++)
|
||||||
|
digest[j] = (uint8_t)(pdf->encryption_key[j] ^ i);
|
||||||
|
|
||||||
|
_pdfioCryptoRC4Init(&rc4, digest, 16);
|
||||||
|
_pdfioCryptoRC4Crypt(&rc4, pdf->user_key, sizeof(pdf->user_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save everything in the dictionary...
|
||||||
|
pdfioDictSetNumber(dict, "Length", 128);
|
||||||
|
pdfioDictSetBinary(dict, "O", pdf->owner_key, sizeof(pdf->owner_key));
|
||||||
|
pdfioDictSetNumber(dict, "P", (int)permissions);
|
||||||
|
pdfioDictSetNumber(dict, "R", encryption == PDFIO_ENCRYPTION_RC4_128 ? 3 : 4);
|
||||||
|
pdfioDictSetNumber(dict, "V", encryption == PDFIO_ENCRYPTION_RC4_128 ? 3 : 4);
|
||||||
|
pdfioDictSetBinary(dict, "U", pdf->user_key, sizeof(pdf->user_key));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PDFIO_ENCRYPTION_AES_256 :
|
||||||
|
// TODO: Implement AES-256 (/V 6 /R 6)
|
||||||
|
|
||||||
|
default :
|
||||||
|
_pdfioFileError(pdf, "Encryption mode %d not supported for writing.", (int)encryption);
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pdf->encrypt_obj = pdfioFileCreateObj(pdf, dict)) == NULL)
|
||||||
|
{
|
||||||
|
_pdfioFileError(pdf, "Unable to create encryption object.");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
pdfioObjClose(pdf->encrypt_obj);
|
||||||
|
|
||||||
|
pdf->encryption = encryption;
|
||||||
|
pdf->permissions = permissions;
|
||||||
|
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// 'pdfioFileSetSubject()' - Set the subject for a PDF file.
|
// 'pdfioFileSetSubject()' - Set the subject for a PDF file.
|
||||||
//
|
//
|
||||||
|
|
||||||
void
|
void
|
||||||
pdfioFileSetSubject(pdfio_file_t *pdf, // I - PDF file
|
pdfioFileSetSubject(
|
||||||
const char *value)// I - Value
|
pdfio_file_t *pdf, // I - PDF file
|
||||||
|
const char *value) // I - Value
|
||||||
{
|
{
|
||||||
if (pdf && pdf->info)
|
if (pdf && pdf->info)
|
||||||
pdfioDictSetString(pdf->info->value.value.dict, "Subject", pdfioStringCreate(pdf, value));
|
pdfioDictSetString(pdf->info->value.value.dict, "Subject", pdfioStringCreate(pdf, value));
|
||||||
@ -1702,9 +1908,9 @@ load_xref(pdfio_file_t *pdf, // I - PDF file
|
|||||||
|
|
||||||
PDFIO_DEBUG("load_xref: Root=%p(%lu)\n", pdf->root, (unsigned long)pdf->root->number);
|
PDFIO_DEBUG("load_xref: Root=%p(%lu)\n", pdf->root, (unsigned long)pdf->root->number);
|
||||||
|
|
||||||
pdf->info = pdfioDictGetObj(pdf->trailer, "Info");
|
pdf->info = pdfioDictGetObj(pdf->trailer, "Info");
|
||||||
pdf->encrypt = pdfioDictGetObj(pdf->trailer, "Encrypt");
|
pdf->encrypt_obj = pdfioDictGetObj(pdf->trailer, "Encrypt");
|
||||||
pdf->id_array = pdfioDictGetArray(pdf->trailer, "ID");
|
pdf->id_array = pdfioDictGetArray(pdf->trailer, "ID");
|
||||||
|
|
||||||
return (load_pages(pdf, pdfioDictGetObj(pdfioObjGetDict(pdf->root), "Pages")));
|
return (load_pages(pdf, pdfioDictGetObj(pdfioObjGetDict(pdf->root), "Pages")));
|
||||||
}
|
}
|
||||||
@ -1819,8 +2025,8 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdf->encrypt)
|
if (pdf->encrypt_obj)
|
||||||
pdfioDictSetObj(pdf->trailer, "Encrypt", pdf->encrypt);
|
pdfioDictSetObj(pdf->trailer, "Encrypt", pdf->encrypt_obj);
|
||||||
if (pdf->id_array)
|
if (pdf->id_array)
|
||||||
pdfioDictSetArray(pdf->trailer, "ID", pdf->id_array);
|
pdfioDictSetArray(pdf->trailer, "ID", pdf->id_array);
|
||||||
pdfioDictSetObj(pdf->trailer, "Info", pdf->info);
|
pdfioDictSetObj(pdf->trailer, "Info", pdf->info);
|
||||||
|
@ -255,6 +255,12 @@ struct _pdfio_file_s // PDF file structure
|
|||||||
pdfio_error_cb_t error_cb; // Error callback
|
pdfio_error_cb_t error_cb; // Error callback
|
||||||
void *error_data; // Data for error callback
|
void *error_data; // Data for error callback
|
||||||
|
|
||||||
|
pdfio_encryption_t encryption; // Encryption mode
|
||||||
|
pdfio_permission_t permissions; // Access permissions (encrypted PDF files)
|
||||||
|
uint8_t encryption_key[16], // Object encryption key
|
||||||
|
owner_key[32], // Owner encryption key
|
||||||
|
user_key[32]; // User encryption key
|
||||||
|
|
||||||
// Active file data
|
// Active file data
|
||||||
int fd; // File descriptor
|
int fd; // File descriptor
|
||||||
char buffer[8192], // Read/write buffer
|
char buffer[8192], // Read/write buffer
|
||||||
@ -265,7 +271,7 @@ struct _pdfio_file_s // PDF file structure
|
|||||||
pdfio_obj_t *root; // Root object/dictionary
|
pdfio_obj_t *root; // Root object/dictionary
|
||||||
pdfio_obj_t *info; // Information object
|
pdfio_obj_t *info; // Information object
|
||||||
pdfio_obj_t *pages_root; // Root pages object
|
pdfio_obj_t *pages_root; // Root pages object
|
||||||
pdfio_obj_t *encrypt; // Encryption object/dictionary
|
pdfio_obj_t *encrypt_obj; // De/Encryption object/dictionary
|
||||||
pdfio_obj_t *cp1252_obj, // CP1252 font encoding object
|
pdfio_obj_t *cp1252_obj, // CP1252 font encoding object
|
||||||
*unicode_obj; // Unicode font encoding object
|
*unicode_obj; // Unicode font encoding object
|
||||||
pdfio_array_t *id_array; // ID array
|
pdfio_array_t *id_array; // ID array
|
||||||
|
24
pdfio.h
24
pdfio.h
@ -59,6 +59,14 @@ typedef struct _pdfio_file_s pdfio_file_t;
|
|||||||
// PDF file
|
// PDF file
|
||||||
typedef bool (*pdfio_error_cb_t)(pdfio_file_t *pdf, const char *message, void *data);
|
typedef bool (*pdfio_error_cb_t)(pdfio_file_t *pdf, const char *message, void *data);
|
||||||
// Error callback
|
// Error callback
|
||||||
|
typedef enum pdfio_encryption_e // PDF encryption modes
|
||||||
|
{
|
||||||
|
PDFIO_ENCRYPTION_NONE = 0, // No encryption
|
||||||
|
PDFIO_ENCRYPTION_RC4_40, // 40-bit RC4 encryption (PDF 1.3)
|
||||||
|
PDFIO_ENCRYPTION_RC4_128, // 128-bit RC4 encryption (PDF 1.4)
|
||||||
|
PDFIO_ENCRYPTION_AES_128, // 128-bit AES encryption (PDF 1.6)
|
||||||
|
PDFIO_ENCRYPTION_AES_256 // 256-bit AES encryption (PDF 2.0)
|
||||||
|
} pdfio_encryption_t;
|
||||||
typedef enum pdfio_filter_e // Compression/decompression filters for streams
|
typedef enum pdfio_filter_e // Compression/decompression filters for streams
|
||||||
{
|
{
|
||||||
PDFIO_FILTER_NONE, // No filter
|
PDFIO_FILTER_NONE, // No filter
|
||||||
@ -78,6 +86,20 @@ typedef ssize_t (*pdfio_output_cb_t)(void *ctx, const void *data, size_t datalen
|
|||||||
// Output callback for pdfioFileCreateOutput
|
// Output callback for pdfioFileCreateOutput
|
||||||
typedef const char *(*pdfio_password_cb_t)(void *data, const char *filename);
|
typedef const char *(*pdfio_password_cb_t)(void *data, const char *filename);
|
||||||
// Password callback for pdfioFileOpen
|
// Password callback for pdfioFileOpen
|
||||||
|
enum pdfio_permission_e // PDF permission bits
|
||||||
|
{
|
||||||
|
PDFIO_PERMISSION_NONE = 0, // No permissions
|
||||||
|
PDFIO_PERMISSION_PRINT = 0x0004, // PDF allows printing
|
||||||
|
PDFIO_PERMISSION_MODIFY = 0x0008, // PDF allows modification
|
||||||
|
PDFIO_PERMISSION_COPY = 0x0010, // PDF allows copying
|
||||||
|
PDFIO_PERMISSION_ANNOTATE = 0x0020, // PDF allows annotation
|
||||||
|
PDFIO_PERMISSION_FORMS = 0x0100, // PDF allows filling in forms
|
||||||
|
PDFIO_PERMISSION_READING = 0x0200, // PDF allows screen reading/accessibility (deprecated in PDF 2.0)
|
||||||
|
PDFIO_PERMISSION_ASSEMBLE = 0x0400, // PDF allows assembly (insert, delete, or rotate pages, add document outlines and thumbnails)
|
||||||
|
PDFIO_PERMISSION_PRINT_HIGH = 0x0800, // PDF allows high quality printing
|
||||||
|
PDFIO_PERMISSION_ALL = ~0 // All permissions
|
||||||
|
};
|
||||||
|
typedef unsigned pdfio_permission_t; // PDF permission bitfield
|
||||||
typedef struct pdfio_rect_s // PDF rectangle
|
typedef struct pdfio_rect_s // PDF rectangle
|
||||||
{
|
{
|
||||||
double x1; // Lower-left X coordinate
|
double x1; // Lower-left X coordinate
|
||||||
@ -174,6 +196,7 @@ extern size_t pdfioFileGetNumObjs(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
|||||||
extern size_t pdfioFileGetNumPages(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
extern size_t pdfioFileGetNumPages(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||||
extern pdfio_obj_t *pdfioFileGetObj(pdfio_file_t *pdf, size_t n) _PDFIO_PUBLIC;
|
extern pdfio_obj_t *pdfioFileGetObj(pdfio_file_t *pdf, size_t n) _PDFIO_PUBLIC;
|
||||||
extern pdfio_obj_t *pdfioFileGetPage(pdfio_file_t *pdf, size_t n) _PDFIO_PUBLIC;
|
extern pdfio_obj_t *pdfioFileGetPage(pdfio_file_t *pdf, size_t n) _PDFIO_PUBLIC;
|
||||||
|
extern pdfio_permission_t pdfioFileGetPermissions(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||||
extern const char *pdfioFileGetProducer(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
extern const char *pdfioFileGetProducer(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||||
extern const char *pdfioFileGetSubject(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
extern const char *pdfioFileGetSubject(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||||
extern const char *pdfioFileGetTitle(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
extern const char *pdfioFileGetTitle(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||||
@ -183,6 +206,7 @@ extern void pdfioFileSetAuthor(pdfio_file_t *pdf, const char *value) _PDFIO_PUB
|
|||||||
extern void pdfioFileSetCreationDate(pdfio_file_t *pdf, time_t value) _PDFIO_PUBLIC;
|
extern void pdfioFileSetCreationDate(pdfio_file_t *pdf, time_t value) _PDFIO_PUBLIC;
|
||||||
extern void pdfioFileSetCreator(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
extern void pdfioFileSetCreator(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
||||||
extern void pdfioFileSetKeywords(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
extern void pdfioFileSetKeywords(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
||||||
|
extern bool pdfioFileSetPermissions(pdfio_file_t *pdf, pdfio_permission_t permissions, pdfio_encryption_t encryption, const char *owner_password, const char *user_password) _PDFIO_PUBLIC;
|
||||||
extern void pdfioFileSetSubject(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
extern void pdfioFileSetSubject(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
||||||
extern void pdfioFileSetTitle(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
extern void pdfioFileSetTitle(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user