Skip to content

Commit d404353

Browse files
nicolaasuniCopilot
andcommitted
feat: add fileOptions to Tcpdf constructor, fix inline HTML wrap continuation, and sync fileid from encryption object
- Tcpdf/initClassObjects: add optional $fileOptions (TFileOptions) parameter to configure ObjFile; remote URL loading is disabled by default and requires an explicit allowedHosts whitelist (security hardening) - fix some issues with HTML inline layout - add Text Unicode Substitution - fixed issue with encryption - new example E045_encryption_and_permissions.php Co-authored-by: Copilot <copilot@github.com>
1 parent 21532fd commit d404353

16 files changed

Lines changed: 503 additions & 48 deletions

README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ If this library saves you time, please consider [supporting its development via
2424
- [Installation](#installation)
2525
- [Font Setup](#font-setup)
2626
- [Quick Start](#quick-start)
27+
- [Remote Resources and fileOptions](#remote-resources-and-fileoptions)
2728
- [Digital Signatures](#digital-signatures)
2829
- [PDF/X Conformance](#pdfx-conformance)
2930
- [PDF/UA Accessibility](#pdfua-accessibility)
@@ -276,6 +277,57 @@ If the minimal example fails on first run, verify these two points first:
276277

277278
---
278279

280+
## Remote Resources and `fileOptions`
281+
282+
By default `tc-lib-pdf` **does not fetch any remote URLs**. Images, fonts, and SVG files referenced by HTTP or HTTPS are blocked unless you explicitly allow the originating hosts. Local file paths are never restricted.
283+
284+
Remote access is controlled by the optional `$fileOptions` array passed as the last argument to the `Tcpdf` constructor (and forwarded to `initClassObjects()`).
285+
286+
### Allowing remote hosts
287+
288+
```php
289+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(
290+
unit: 'mm',
291+
fileOptions: [
292+
'allowedHosts' => ['cdn.example.com', 'assets.myapp.io'],
293+
],
294+
);
295+
```
296+
297+
Only the listed host names are permitted. Any attempt to load a resource from an unlisted host is silently blocked. Supply an explicit allowlist rather than a wildcard to limit the attack surface when user-supplied URLs might reach this code path.
298+
299+
### All `fileOptions` keys
300+
301+
| Key | Type | Default | Description |
302+
|-----|------|---------|-------------|
303+
| `allowedHosts` | `string[]` | `[]` (none) | Host names the library may fetch over HTTP/HTTPS. Remote loading is disabled when this list is empty. |
304+
| `maxRemoteSize` | `int` | `52428800` (50 MiB) | Maximum bytes accepted for a single remote download. Requests exceeding this limit are aborted. |
305+
| `curlopts` | `array<int, bool\|int\|string>` | `[]` | Per-request cURL options (keyed by `CURLOPT_*` constants) merged on top of the built-in defaults. |
306+
| `defaultCurlOpts` | `array<int, bool\|int\|string>` | `null` | Replaces the built-in default cURL option set entirely. Omit this key to keep the safe defaults. |
307+
| `fixedCurlOpts` | `array<int, bool\|int\|string>` | `null` | cURL options that are always enforced and cannot be overridden by `curlopts` — useful for pinning TLS settings in locked-down environments. |
308+
309+
### Example: pinning TLS and setting a short timeout
310+
311+
```php
312+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(
313+
unit: 'mm',
314+
fileOptions: [
315+
'allowedHosts' => ['cdn.example.com'],
316+
'maxRemoteSize' => 10 * 1024 * 1024, // 10 MiB
317+
'curlopts' => [
318+
CURLOPT_TIMEOUT => 10,
319+
CURLOPT_CONNECTTIMEOUT => 5,
320+
],
321+
'fixedCurlOpts' => [
322+
CURLOPT_SSL_VERIFYPEER => true,
323+
CURLOPT_SSL_VERIFYHOST => 2,
324+
],
325+
],
326+
);
327+
```
328+
329+
---
330+
279331
## Digital Signatures
280332

281333
`tc-lib-pdf` supports detached CMS (PKCS#7) signatures with optional RFC 3161 timestamps and LTV (Long-Term Validation) material, all embedded in a single PDF revision.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8.10.4
1+
8.11.0

composer.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@
2323
"ext-date": "*",
2424
"ext-pcre": "*",
2525
"tecnickcom/tc-lib-barcode": "^2.4",
26-
"tecnickcom/tc-lib-color": "^2.4",
27-
"tecnickcom/tc-lib-pdf-image": "^2.1",
28-
"tecnickcom/tc-lib-pdf-font": "^2.6",
29-
"tecnickcom/tc-lib-file": "^2.3",
30-
"tecnickcom/tc-lib-pdf-encrypt": "^2.1",
26+
"tecnickcom/tc-lib-color": "^2.5",
27+
"tecnickcom/tc-lib-pdf-image": "^2.2",
28+
"tecnickcom/tc-lib-pdf-font": "^2.7",
29+
"tecnickcom/tc-lib-file": "^2.5",
30+
"tecnickcom/tc-lib-pdf-encrypt": "^2.2",
3131
"tecnickcom/tc-lib-unicode-data": "^2.0",
32-
"tecnickcom/tc-lib-unicode": "^2.0",
32+
"tecnickcom/tc-lib-unicode": "^2.1",
3333
"tecnickcom/tc-lib-pdf-page": "^4.3",
3434
"tecnickcom/tc-lib-pdf-graph": "^2.4"
3535
},

examples/E031_html_features.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,19 @@
350350

351351
// ----------
352352

353+
// HTML E-L
354+
355+
$html_05L = '<p>Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India Juliett Kilo. Lima Mike November Oscar Papa Quebec Romeo (<em>Sierra-Tango</em>) Uniform Victor Whiskey (<em>Xray-Yankee</em>). Zulu. Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India Juliett Kilo. Lima Mike November Oscar Papa Quebec Romeo (<em>Sierra-Tango</em>) Uniform Victor Whiskey (<em>Xray-Yankee</em>). Zulu. Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India Juliett Kilo. Lima Mike November Oscar Papa Quebec Romeo (<em>Sierra-Tango</em>) Uniform Victor Whiskey (<em>Xray-Yankee</em>). Zulu.</p>';
356+
357+
$pdf->addHTMLCell(
358+
$html_05L,
359+
20,
360+
100,
361+
180,
362+
);
363+
364+
// ----------
365+
353366
// HTML E-B
354367

355368
$pageV05B = $pdf->addPage();
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
/**
3+
* E045_encryption_and_permissions.php
4+
*
5+
* @since 2026-04-27
6+
* @category Library
7+
* @package Pdf
8+
* @author Nicola Asuni <info@tecnick.com>
9+
* @copyright 2002-2026 Nicola Asuni - Tecnick.com LTD
10+
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
11+
* @link https://github.com/tecnickcom/tc-lib-pdf
12+
*
13+
* This file is part of tc-lib-pdf software library.
14+
*/
15+
16+
// NOTE: run make deps fonts in the project root to generate the dependencies and example fonts.
17+
18+
// autoloader when using Composer
19+
require(__DIR__ . '/../vendor/autoload.php');
20+
21+
// define fonts directory
22+
\define('K_PATH_FONTS', \realpath(__DIR__ . '/../vendor/tecnickcom/tc-lib-pdf-font/target/fonts'));
23+
24+
// autoloader when using RPM or DEB package installation
25+
//require ('/usr/share/php/Com/Tecnick/Pdf/autoload.php');
26+
27+
$fileId = \md5('E045_encryption_and_permissions');
28+
$encrypt = new \Com\Tecnick\Pdf\Encrypt\Encrypt(
29+
true,
30+
$fileId,
31+
2,
32+
['modify', 'copy', 'annot-forms', 'assemble'],
33+
'demo-user',
34+
'demo-owner'
35+
);
36+
37+
// main TCPDF object
38+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(
39+
'mm', // string $unit = 'mm',
40+
true, // bool $isunicode = true,
41+
false, // bool $subsetfont = false,
42+
true, // bool $compress = true,
43+
'', // string $mode = '',
44+
$encrypt, // ?ObjEncrypt $objEncrypt = null,
45+
);
46+
47+
// ----------
48+
49+
50+
$pdf->setCreator('tc-lib-pdf');
51+
$pdf->setAuthor('Nicola Asuni');
52+
$pdf->setSubject('tc-lib-pdf example: 045');
53+
$pdf->setTitle('HTML Features Example');
54+
$pdf->setKeywords('TCPDF tc-lib-pdf example Encryption and Permissions');
55+
$pdf->setPDFFilename('E045_encryption_and_permissions.pdf');
56+
57+
$pdf->setViewerPreferences(['DisplayDocTitle' => true]);
58+
59+
$pdf->enableDefaultPageContent();
60+
61+
// ----------
62+
// Insert fonts
63+
64+
$bfont = $pdf->font->insert($pdf->pon, 'helvetica', '', 10);
65+
66+
$page01 = $pdf->addPage();
67+
$pdf->page->addContent($bfont['out']);
68+
69+
$html = <<<HTML
70+
<h1>Encryption and Permissions</h1>
71+
<p>This document demonstrates PDF encryption and permission controls using tc-lib-pdf.
72+
The file is protected with a user password (<em>demo-user</em>) and an owner password (<em>demo-owner</em>).
73+
Encryption restricts unauthorized access while the owner password grants full control.
74+
The allowed permissions for this document are: <strong>modify</strong>, <strong>copy</strong>,
75+
<strong>annot-forms</strong>, and <strong>assemble</strong>.
76+
All other operations, such as printing, are denied.</p>
77+
HTML;
78+
79+
$pdf->addHTMLCell(
80+
$html,
81+
20,
82+
10,
83+
180,
84+
);
85+
86+
// ----------
87+
88+
// get PDF document as raw string
89+
$rawpdf = $pdf->getOutPDFString();
90+
91+
// Various output modes:
92+
93+
//$pdf->savePDF(\dirname(__DIR__).'/target', $rawpdf);
94+
$pdf->renderPDF($rawpdf);
95+
//$pdf->downloadPDF($rawpdf);
96+
//echo $pdf->getMIMEAttachmentPDF($rawpdf);

examples/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ This index lists all runnable examples bundled with tc-lib-pdf, from foundationa
4747
- [E042_html_form.php](E042_html_form.php): XHTML form-to-PDF mapping example for inputs, selects, textarea, and actions.
4848
- [E043_html_tables.php](E043_html_tables.php): HTML table layout showcase including colspan/rowspan, nested tables, and CSS styling.
4949
- [E044_toc_index.php](E044_toc_index.php): Bookmark outline example with generated table of contents via addTOC.
50+
- [E045_encryption_and_permissions.php](E045_encryption_and_permissions.php): PDF encryption and permission controls with user and owner passwords.

resources/debian/control

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,23 @@ Provides: php-~#PROJECT#~
1414
Architecture: all
1515
Depends: php (>= 8.1.0), php-date,
1616
php-tecnickcom-tc-lib-barcode (<< 3.0.0),
17-
php-tecnickcom-tc-lib-barcode (>= 2.4.36),
17+
php-tecnickcom-tc-lib-barcode (>= 2.4.37),
1818
php-tecnickcom-tc-lib-color (<< 3.0.0),
19-
php-tecnickcom-tc-lib-color (>= 2.4.1),
19+
php-tecnickcom-tc-lib-color (>= 2.5.0),
2020
php-tecnickcom-tc-lib-file (<< 3.0.0),
21-
php-tecnickcom-tc-lib-file (>= 2.3.9),
21+
php-tecnickcom-tc-lib-file (>= 2.5.0),
2222
php-tecnickcom-tc-lib-pdf-encrypt (<< 3.0.0),
23-
php-tecnickcom-tc-lib-pdf-encrypt (>= 2.1.43),
23+
php-tecnickcom-tc-lib-pdf-encrypt (>= 2.2.0),
2424
php-tecnickcom-tc-lib-pdf-font (<< 3.0.0),
25-
php-tecnickcom-tc-lib-pdf-font (>= 2.6.41),
25+
php-tecnickcom-tc-lib-pdf-font (>= 2.7.0),
2626
php-tecnickcom-tc-lib-pdf-graph (<< 3.0.0),
27-
php-tecnickcom-tc-lib-pdf-graph (>= 2.4.20),
27+
php-tecnickcom-tc-lib-pdf-graph (>= 2.4.21),
2828
php-tecnickcom-tc-lib-pdf-image (<< 3.0.0),
29-
php-tecnickcom-tc-lib-pdf-image (>= 2.1.41),
29+
php-tecnickcom-tc-lib-pdf-image (>= 2.2.0),
3030
php-tecnickcom-tc-lib-pdf-page (<< 5.0.0),
31-
php-tecnickcom-tc-lib-pdf-page (>= 4.3.20),
31+
php-tecnickcom-tc-lib-pdf-page (>= 4.3.21),
3232
php-tecnickcom-tc-lib-unicode (<< 3.0.0),
33-
php-tecnickcom-tc-lib-unicode (>= 2.0.52),
33+
php-tecnickcom-tc-lib-unicode (>= 2.1.0),
3434
php-tecnickcom-tc-lib-unicode-data (<< 3.0.0),
3535
php-tecnickcom-tc-lib-unicode-data (>= 2.0.51),
3636
${misc:Depends}

resources/rpm/rpm.spec

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,25 @@ Requires: php(language) >= 8.1.0
1818
Requires: php-date
1919
Requires: php-pcre
2020
Requires: php-composer(%{c_vendor}/tc-lib-barcode) < 3.0.0
21-
Requires: php-composer(%{c_vendor}/tc-lib-barcode) >= 2.4.36
21+
Requires: php-composer(%{c_vendor}/tc-lib-barcode) >= 2.4.37
2222
Requires: php-composer(%{c_vendor}/tc-lib-color) < 3.0.0
23-
Requires: php-composer(%{c_vendor}/tc-lib-color) >= 2.4.1
23+
Requires: php-composer(%{c_vendor}/tc-lib-color) >= 2.5.0
2424
Requires: php-composer(%{c_vendor}/tc-lib-pdf-image) < 3.0.0
25-
Requires: php-composer(%{c_vendor}/tc-lib-pdf-image) >= 2.1.41
25+
Requires: php-composer(%{c_vendor}/tc-lib-pdf-image) >= 2.2.0
2626
Requires: php-composer(%{c_vendor}/tc-lib-pdf-font) < 3.0.0
27-
Requires: php-composer(%{c_vendor}/tc-lib-pdf-font) >= 2.6.41
27+
Requires: php-composer(%{c_vendor}/tc-lib-pdf-font) >= 2.7.0
2828
Requires: php-composer(%{c_vendor}/tc-lib-file) < 3.0.0
29-
Requires: php-composer(%{c_vendor}/tc-lib-file) >= 2.3.9
29+
Requires: php-composer(%{c_vendor}/tc-lib-file) >= 2.5.0
3030
Requires: php-composer(%{c_vendor}/tc-lib-pdf-encrypt) < 3.0.0
31-
Requires: php-composer(%{c_vendor}/tc-lib-pdf-encrypt) >= 2.1.43
31+
Requires: php-composer(%{c_vendor}/tc-lib-pdf-encrypt) >= 2.2.0
3232
Requires: php-composer(%{c_vendor}/tc-lib-unicode-data) < 3.0.0
3333
Requires: php-composer(%{c_vendor}/tc-lib-unicode-data) >= 2.0.51
3434
Requires: php-composer(%{c_vendor}/tc-lib-unicode) < 3.0.0
35-
Requires: php-composer(%{c_vendor}/tc-lib-unicode) >= 2.0.52
35+
Requires: php-composer(%{c_vendor}/tc-lib-unicode) >= 2.1.0
3636
Requires: php-composer(%{c_vendor}/tc-lib-pdf-page) < 5.0.0
37-
Requires: php-composer(%{c_vendor}/tc-lib-pdf-page) >= 4.3.20
37+
Requires: php-composer(%{c_vendor}/tc-lib-pdf-page) >= 4.3.21
3838
Requires: php-composer(%{c_vendor}/tc-lib-pdf-graph) < 3.0.0
39-
Requires: php-composer(%{c_vendor}/tc-lib-pdf-graph) >= 2.4.20
39+
Requires: php-composer(%{c_vendor}/tc-lib-pdf-graph) >= 2.4.21
4040

4141
Provides: php-composer(%{c_vendor}/%{gh_project}) = %{version}
4242
Provides: php-%{gh_project} = %{version}

src/Base.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ abstract class Base
189189
/**
190190
* TCPDF version.
191191
*/
192-
protected string $version = '8.10.4';
192+
protected string $version = '8.11.0';
193193

194194
/**
195195
* Time is seconds since EPOCH when the document was created.

src/ClassObjects.php

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,47 @@
4141
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
4242
* @link https://github.com/tecnickcom/tc-lib-pdf
4343
*
44+
* @phpstan-type TFileOptions array{
45+
* allowedHosts?: array<string>,
46+
* maxRemoteSize?: int,
47+
* curlopts?: array<int, bool|int|string>,
48+
* defaultCurlOpts?: array<int, bool|int|string>,
49+
* fixedCurlOpts?: array<int, bool|int|string>
50+
* }
51+
*
4452
* @SuppressWarnings("PHPMD.DepthOfInheritance")
4553
*/
4654
abstract class ClassObjects extends \Com\Tecnick\Pdf\Output
4755
{
4856
/**
4957
* Initialize dependencies class objects.
5058
*
51-
* @param ?ObjEncrypt $objEncrypt Encryption object.
59+
* @param ?ObjEncrypt $objEncrypt Encryption object.
60+
* @param TFileOptions|null $fileOptions Optional configuration for the shared file helper used
61+
* to load external resources (images, fonts, SVG, etc.).
62+
* Supported keys:
63+
* - allowedHosts (string[]): Whitelist of host names that
64+
* the library is allowed to fetch over HTTP/HTTPS. For
65+
* security reasons remote URL loading is DISABLED by
66+
* default; you MUST populate this list (for example
67+
* ['example.com', 'cdn.example.com']) to enable any
68+
* remote download. Local file paths are not affected.
69+
* - maxRemoteSize (int): Maximum size in bytes accepted
70+
* for a remote download (default 52428800 = 50 MiB).
71+
* - curlopts (array<int,bool|int|string>): Per-request
72+
* cURL options merged on top of the defaults (keys are
73+
* CURLOPT_* constants).
74+
* - defaultCurlOpts (array<int,bool|int|string>):
75+
* Replaces the built-in default cURL options. Use with
76+
* care; omit to keep the safe defaults.
77+
* - fixedCurlOpts (array<int,bool|int|string>): cURL
78+
* options that are always enforced and cannot be
79+
* overridden by curlopts (for example to pin TLS
80+
* settings).
5281
*/
5382
public function initClassObjects(
54-
?ObjEncrypt $objEncrypt = null
83+
?ObjEncrypt $objEncrypt = null,
84+
?array $fileOptions = null
5585
): void {
5686
if ($objEncrypt instanceof ObjEncrypt) {
5787
$this->encrypt = $objEncrypt;
@@ -62,7 +92,13 @@ public function initClassObjects(
6292
$this->color = new ObjPdfColor();
6393
$this->color->setForceDeviceCmyk($this->requiresPdfxDeviceCmyk());
6494
$this->barcode = new ObjBarcode();
65-
$this->file = new ObjFile();
95+
$this->file = new ObjFile(
96+
$fileOptions['allowedHosts'] ?? [],
97+
$fileOptions['maxRemoteSize'] ?? 52428800,
98+
$fileOptions['curlopts'] ?? [],
99+
$fileOptions['defaultCurlOpts'] ?? null,
100+
$fileOptions['fixedCurlOpts'] ?? null,
101+
);
66102
$this->cache = new ObjCache();
67103
$this->uniconv = new ObjUniConvert();
68104

@@ -95,13 +131,15 @@ public function initClassObjects(
95131
$this->subsetfont,
96132
$this->isunicode,
97133
$pdfamode,
134+
$fileOptions,
98135
);
99136

100137
$this->image = new ObjImage(
101138
$this->kunit,
102139
$this->encrypt,
103140
$pdfamode,
104141
$this->compress,
142+
$fileOptions,
105143
);
106144
}
107145
}

0 commit comments

Comments
 (0)