Skip to content
Permalink
Browse files

Fix support for image URLs

  • Loading branch information...
nicolaasuni committed Sep 23, 2018
1 parent aee50eb commit a5135e2cf02f8c935b71e9e7d676f0f1d31b1b9d
Showing with 126 additions and 99 deletions.
  1. +3 −0 CHANGELOG.TXT
  2. +1 −1 composer.json
  3. +6 −7 include/tcpdf_static.php
  4. +116 −91 tcpdf.php
@@ -1,3 +1,6 @@
6.2.25
- Fix support for image URLs.

This comment has been minimized.

Copy link
@staabm

staabm Oct 5, 2018

with this version using images in PDFs with a local path no longer works for us.
it does work with 6.2.17. (we didn't test the versions in between)

the html we generate looks like

<table>
                                    <tr>
                                        <td width="25"><br><br><img src="/cluster/www/www/files/customer/files/artfarbe/3/4/2/9/4/files/master_60x70.jpg" width="60" height="70" border="0" /></td>
                                        <td><br><br><br>royal</td>
                                    </tr>
                                </table>

This comment has been minimized.

Copy link
@Kanti

Kanti Oct 12, 2018

We have a similar problem, but with data URLs:

With version 6.2.17 it works but with 6.2.25 it does not.

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB9AAAAYiCAYAAABkF........"" />

This comment has been minimized.

Copy link
@pdanny

pdanny Oct 12, 2018

I can confirm that data URLs do not work in 6.2.25. Version 6.2.17 seems to be ok.

We have a similar problem, but with data URLs:

With version 6.2.17 it works but with 6.2.25 it does not.

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB9AAAAYiCAYAAABkF........"" />

This comment has been minimized.

Copy link
@Kanti

Kanti Oct 17, 2018

still not working in 6.2.26

This comment has been minimized.

Copy link
@Vprok

Vprok Jan 16, 2019

Relative URLs without width and height don't work after this fix.


6.2.24
- Support remote urls when checking if file exists.

@@ -1,6 +1,6 @@
{
"name": "tecnickcom/tcpdf",
"version": "6.2.24",
"version": "6.2.25",
"homepage": "http://www.tcpdf.org/",
"type": "library",
"description": "TCPDF is a PHP class for generating PDF documents and barcodes.",
@@ -55,7 +55,7 @@ class TCPDF_STATIC {
* Current TCPDF version.
* @private static
*/
private static $tcpdf_version = '6.2.24';
private static $tcpdf_version = '6.2.25';
/**
* String alias for total number of pages.
@@ -1855,14 +1855,13 @@ public static function url_exists($url) {
* @public static
*/
public static function file_exists($filename) {
$httpmode = (preg_match('|^https?://|', $filename) == 1);
if (!$httpmode && strpos($filename, '://')) {
return false; // only support http and https wrappers for security reasons
if (preg_match('|^https?://|', $filename) == 1) {
return self::url_exists($filename);
}
if (@file_exists($filename) || ($httpmode && self::url_exists($filename))) {
return true;
if (strpos($filename, '://')) {
return false; // only support http and https wrappers for security reasons
}
return false;
return @file_exists($filename);
}
/**
207 tcpdf.php
@@ -1,7 +1,7 @@
<?php
//============================================================+
// File name : tcpdf.php
// Version : 6.2.24
// Version : 6.2.25
// Begin : 2002-08-03
// Last Update : 2018-09-14
// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
@@ -104,7 +104,7 @@
* Tools to encode your unicode fonts are on fonts/utils directory.</p>
* @package com.tecnick.tcpdf
* @author Nicola Asuni
* @version 6.2.24
* @version 6.2.25
*/
// TCPDF configuration
@@ -128,7 +128,7 @@
* TCPDF project (http://www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.<br>
* @package com.tecnick.tcpdf
* @brief PHP class for generating PDF documents without requiring external extensions.
* @version 6.2.24
* @version 6.2.25
* @author Nicola Asuni - info@tecnick.com
* @IgnoreAnnotation("protected")
* @IgnoreAnnotation("public")
@@ -18817,100 +18817,122 @@ protected function openHTMLTagHandler($dom, $key, $cell) {
break;
}
case 'img': {
if (!empty($tag['attribute']['src'])) {
if ($tag['attribute']['src'][0] === '@') {
// data stream
$tag['attribute']['src'] = '@'.base64_decode(substr($tag['attribute']['src'], 1));
$type = '';
} else {
// get image type
$type = TCPDF_IMAGES::getImageFileType($tag['attribute']['src']);
}
if (!isset($tag['width'])) {
$tag['width'] = 0;
}
if (!isset($tag['height'])) {
$tag['height'] = 0;
}
//if (!isset($tag['attribute']['align'])) {
// the only alignment supported is "bottom"
// further development is required for other modes.
$tag['attribute']['align'] = 'bottom';
//}
switch($tag['attribute']['align']) {
case 'top': {
$align = 'T';
break;
}
case 'middle': {
$align = 'M';
break;
}
case 'bottom': {
$align = 'B';
break;
if (empty($tag['attribute']['src'])) {
break;
}
$imgsrc = $tag['attribute']['src'];
if ($imgsrc[0] === '@') {
// data stream
$imgsrc = '@'.base64_decode(substr($imgsrc, 1));
$type = '';
} else {
if (($imgsrc[0] === '/') AND !empty($_SERVER['DOCUMENT_ROOT']) AND ($_SERVER['DOCUMENT_ROOT'] != '/')) {

This comment has been minimized.

Copy link
@slava-v

slava-v Nov 13, 2018

This is wrong.
I have image files stored somewhere else and not in the DOCUMENT_ROOT.
I use absolute image path.
In result I have the image src prefixed with DOCUMENT_ROOT

This comment has been minimized.

Copy link
@slava-v

slava-v Nov 13, 2018

I mean, it's wrong to assume that everybody keeps image files under document_root. This can be either disabled or made optional with a configuration option

// fix image path
$findroot = strpos($imgsrc, $_SERVER['DOCUMENT_ROOT']);
if (($findroot === false) OR ($findroot > 1)) {
if (substr($_SERVER['DOCUMENT_ROOT'], -1) == '/') {
$imgsrc = substr($_SERVER['DOCUMENT_ROOT'], 0, -1).$imgsrc;
} else {
$imgsrc = $_SERVER['DOCUMENT_ROOT'].$imgsrc;
}
}
default: {
$align = 'B';
break;
$imgsrc = urldecode($imgsrc);
$testscrtype = @parse_url($imgsrc);
if (empty($testscrtype['query'])) {
// convert URL to server path
$imgsrc = str_replace(K_PATH_URL, K_PATH_MAIN, $imgsrc);
} elseif (preg_match('|^https?://|', $imgsrc) !== 1) {
// convert URL to server path
$imgsrc = str_replace(K_PATH_MAIN, K_PATH_URL, $imgsrc);
}
}
$prevy = $this->y;
$xpos = $this->x;
$imglink = '';
if (isset($this->HREF['url']) AND !TCPDF_STATIC::empty_string($this->HREF['url'])) {
$imglink = $this->HREF['url'];
if ($imglink[0] == '#') {
// convert url to internal link
$lnkdata = explode(',', $imglink);
if (isset($lnkdata[0])) {
$page = intval(substr($lnkdata[0], 1));
if (empty($page) OR ($page <= 0)) {
$page = $this->page;
}
if (isset($lnkdata[1]) AND (strlen($lnkdata[1]) > 0)) {
$lnky = floatval($lnkdata[1]);
} else {
$lnky = 0;
}
$imglink = $this->AddLink();
$this->SetLink($imglink, $lnky, $page);
// get image type
$type = TCPDF_IMAGES::getImageFileType($imgsrc);
}
if (!isset($tag['width'])) {
$tag['width'] = 0;
}
if (!isset($tag['height'])) {
$tag['height'] = 0;
}
//if (!isset($tag['attribute']['align'])) {
// the only alignment supported is "bottom"
// further development is required for other modes.
$tag['attribute']['align'] = 'bottom';
//}
switch($tag['attribute']['align']) {
case 'top': {
$align = 'T';
break;
}
case 'middle': {
$align = 'M';
break;
}
case 'bottom': {
$align = 'B';
break;
}
default: {
$align = 'B';
break;
}
}
$prevy = $this->y;
$xpos = $this->x;
$imglink = '';
if (isset($this->HREF['url']) AND !TCPDF_STATIC::empty_string($this->HREF['url'])) {
$imglink = $this->HREF['url'];
if ($imglink[0] == '#') {
// convert url to internal link
$lnkdata = explode(',', $imglink);
if (isset($lnkdata[0])) {
$page = intval(substr($lnkdata[0], 1));
if (empty($page) OR ($page <= 0)) {
$page = $this->page;
}
if (isset($lnkdata[1]) AND (strlen($lnkdata[1]) > 0)) {
$lnky = floatval($lnkdata[1]);
} else {
$lnky = 0;
}
$imglink = $this->AddLink();
$this->SetLink($imglink, $lnky, $page);
}
}
$border = 0;
if (isset($tag['border']) AND !empty($tag['border'])) {
// currently only support 1 (frame) or a combination of 'LTRB'
$border = $tag['border'];
}
$iw = '';
if (isset($tag['width'])) {
$iw = $this->getHTMLUnitToUnits($tag['width'], ($tag['fontsize'] / $this->k), 'px', false);
}
$ih = '';
if (isset($tag['height'])) {
$ih = $this->getHTMLUnitToUnits($tag['height'], ($tag['fontsize'] / $this->k), 'px', false);
}
if (($type == 'eps') OR ($type == 'ai')) {
$this->ImageEps($tag['attribute']['src'], $xpos, $this->y, $iw, $ih, $imglink, true, $align, '', $border, true);
} elseif ($type == 'svg') {
$this->ImageSVG($tag['attribute']['src'], $xpos, $this->y, $iw, $ih, $imglink, $align, '', $border, true);
} else {
$this->Image($tag['attribute']['src'], $xpos, $this->y, $iw, $ih, '', $imglink, $align, false, 300, '', false, false, $border, false, false, true);
}
$border = 0;
if (isset($tag['border']) AND !empty($tag['border'])) {
// currently only support 1 (frame) or a combination of 'LTRB'
$border = $tag['border'];
}
$iw = '';
if (isset($tag['width'])) {
$iw = $this->getHTMLUnitToUnits($tag['width'], ($tag['fontsize'] / $this->k), 'px', false);
}
$ih = '';
if (isset($tag['height'])) {
$ih = $this->getHTMLUnitToUnits($tag['height'], ($tag['fontsize'] / $this->k), 'px', false);
}
if (($type == 'eps') OR ($type == 'ai')) {
$this->ImageEps($imgsrc, $xpos, $this->y, $iw, $ih, $imglink, true, $align, '', $border, true);
} elseif ($type == 'svg') {
$this->ImageSVG($imgsrc, $xpos, $this->y, $iw, $ih, $imglink, $align, '', $border, true);
} else {
$this->Image($imgsrc, $xpos, $this->y, $iw, $ih, '', $imglink, $align, false, 300, '', false, false, $border, false, false, true);
}
switch($align) {
case 'T': {
$this->y = $prevy;
break;
}
switch($align) {
case 'T': {
$this->y = $prevy;
break;
}
case 'M': {
$this->y = (($this->img_rb_y + $prevy - ($this->getCellHeight($tag['fontsize'] / $this->k))) / 2);
break;
}
case 'B': {
$this->y = $this->img_rb_y - ($this->getCellHeight($tag['fontsize'] / $this->k) - ($this->getFontDescent($tag['fontname'], $tag['fontstyle'], $tag['fontsize']) * $this->cell_height_ratio));
break;
}
case 'M': {
$this->y = (($this->img_rb_y + $prevy - ($this->getCellHeight($tag['fontsize'] / $this->k))) / 2);
break;
}
case 'B': {
$this->y = $this->img_rb_y - ($this->getCellHeight($tag['fontsize'] / $this->k) - ($this->getFontDescent($tag['fontname'], $tag['fontstyle'], $tag['fontsize']) * $this->cell_height_ratio));
break;
}
}
break;
@@ -24206,9 +24228,12 @@ protected function startSVGElementHandler($parser, $name, $attribs, $ctm=array()
}
$img = urldecode($img);
$testscrtype = @parse_url($img);
if (!isset($testscrtype['query']) OR empty($testscrtype['query'])) {
if (empty($testscrtype['query'])) {
// convert URL to server path
$img = str_replace(K_PATH_URL, K_PATH_MAIN, $img);
} elseif (preg_match('|^https?://|', $img) !== 1) {
// convert server path to URL
$img = str_replace(K_PATH_MAIN, K_PATH_URL, $img);
}
}
// get image type

2 comments on commit a5135e2

@tecbird

This comment has been minimized.

Copy link

replied Oct 23, 2018

Bad Fix!
We have problems with using "../../" in paths since this version

@NiklasBr

This comment has been minimized.

Copy link
Contributor

replied May 27, 2019

@nicolaasuni Can you revert this one?

Please sign in to comment.
You can’t perform that action at this time.