Pdf.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * PDF schema handling
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. declare(strict_types=1);
  9. namespace PhpMyAdmin\Plugins\Schema\Pdf;
  10. use PhpMyAdmin\Pdf as PdfLib;
  11. use PhpMyAdmin\Relation;
  12. use PhpMyAdmin\Util;
  13. /**
  14. * Skip the plugin if TCPDF is not available.
  15. */
  16. if (! class_exists('TCPDF')) {
  17. $GLOBALS['skip_import'] = true;
  18. return;
  19. }
  20. /**
  21. * block attempts to directly run this script
  22. */
  23. if (getcwd() == __DIR__) {
  24. die('Attack stopped');
  25. }
  26. /**
  27. * Extends the "TCPDF" class and helps
  28. * in developing the structure of PDF Schema Export
  29. *
  30. * @access public
  31. * @package PhpMyAdmin
  32. * @see TCPDF
  33. */
  34. class Pdf extends PdfLib
  35. {
  36. /**
  37. * Defines properties
  38. */
  39. public $_xMin;
  40. public $_yMin;
  41. public $leftMargin = 10;
  42. public $topMargin = 10;
  43. public $scale;
  44. public $PMA_links;
  45. public $Outlines = [];
  46. public $def_outlines;
  47. public $widths;
  48. public $cMargin;
  49. private $_ff = PdfLib::PMA_PDF_FONT;
  50. private $_offline;
  51. private $_pageNumber;
  52. private $_withDoc;
  53. private $_db;
  54. /**
  55. * @var Relation
  56. */
  57. private $relation;
  58. /**
  59. * Constructs PDF for schema export.
  60. *
  61. * @param string $orientation page orientation
  62. * @param string $unit unit
  63. * @param string $paper the format used for pages
  64. * @param int $pageNumber schema page number that is being exported
  65. * @param boolean $withDoc with document dictionary
  66. * @param string $db the database name
  67. *
  68. * @access public
  69. */
  70. public function __construct(
  71. $orientation,
  72. $unit,
  73. $paper,
  74. $pageNumber,
  75. $withDoc,
  76. $db
  77. ) {
  78. parent::__construct($orientation, $unit, $paper);
  79. $this->_pageNumber = $pageNumber;
  80. $this->_withDoc = $withDoc;
  81. $this->_db = $db;
  82. $this->relation = new Relation($GLOBALS['dbi']);
  83. }
  84. /**
  85. * Sets the value for margins
  86. *
  87. * @param float $c_margin margin
  88. *
  89. * @return void
  90. */
  91. public function setCMargin($c_margin)
  92. {
  93. $this->cMargin = $c_margin;
  94. }
  95. /**
  96. * Sets the scaling factor, defines minimum coordinates and margins
  97. *
  98. * @param float|int $scale The scaling factor
  99. * @param float|int $xMin The minimum X coordinate
  100. * @param float|int $yMin The minimum Y coordinate
  101. * @param float|int $leftMargin The left margin
  102. * @param float|int $topMargin The top margin
  103. *
  104. * @return void
  105. */
  106. public function setScale(
  107. $scale = 1,
  108. $xMin = 0,
  109. $yMin = 0,
  110. $leftMargin = -1,
  111. $topMargin = -1
  112. ) {
  113. $this->scale = $scale;
  114. $this->_xMin = $xMin;
  115. $this->_yMin = $yMin;
  116. if ($this->leftMargin != -1) {
  117. $this->leftMargin = $leftMargin;
  118. }
  119. if ($this->topMargin != -1) {
  120. $this->topMargin = $topMargin;
  121. }
  122. }
  123. /**
  124. * Outputs a scaled cell
  125. *
  126. * @param float|int $w The cell width
  127. * @param float|int $h The cell height
  128. * @param string $txt The text to output
  129. * @param mixed $border Whether to add borders or not
  130. * @param integer $ln Where to put the cursor once the output is done
  131. * @param string $align Align mode
  132. * @param integer $fill Whether to fill the cell with a color or not
  133. * @param string $link Link
  134. *
  135. * @return void
  136. *
  137. * @see TCPDF::Cell()
  138. */
  139. public function cellScale(
  140. $w,
  141. $h = 0,
  142. $txt = '',
  143. $border = 0,
  144. $ln = 0,
  145. $align = '',
  146. $fill = 0,
  147. $link = ''
  148. ) {
  149. $h /= $this->scale;
  150. $w /= $this->scale;
  151. $this->Cell($w, $h, $txt, $border, $ln, $align, $fill, $link);
  152. }
  153. /**
  154. * Draws a scaled line
  155. *
  156. * @param float $x1 The horizontal position of the starting point
  157. * @param float $y1 The vertical position of the starting point
  158. * @param float $x2 The horizontal position of the ending point
  159. * @param float $y2 The vertical position of the ending point
  160. *
  161. * @return void
  162. *
  163. * @see TCPDF::Line()
  164. */
  165. public function lineScale($x1, $y1, $x2, $y2)
  166. {
  167. $x1 = ($x1 - $this->_xMin) / $this->scale + $this->leftMargin;
  168. $y1 = ($y1 - $this->_yMin) / $this->scale + $this->topMargin;
  169. $x2 = ($x2 - $this->_xMin) / $this->scale + $this->leftMargin;
  170. $y2 = ($y2 - $this->_yMin) / $this->scale + $this->topMargin;
  171. $this->Line($x1, $y1, $x2, $y2);
  172. }
  173. /**
  174. * Sets x and y scaled positions
  175. *
  176. * @param float $x The x position
  177. * @param float $y The y position
  178. *
  179. * @return void
  180. *
  181. * @see TCPDF::SetXY()
  182. */
  183. public function setXyScale($x, $y)
  184. {
  185. $x = ($x - $this->_xMin) / $this->scale + $this->leftMargin;
  186. $y = ($y - $this->_yMin) / $this->scale + $this->topMargin;
  187. $this->SetXY($x, $y);
  188. }
  189. /**
  190. * Sets the X scaled positions
  191. *
  192. * @param float $x The x position
  193. *
  194. * @return void
  195. *
  196. * @see TCPDF::SetX()
  197. */
  198. public function setXScale($x)
  199. {
  200. $x = ($x - $this->_xMin) / $this->scale + $this->leftMargin;
  201. $this->SetX($x);
  202. }
  203. /**
  204. * Sets the scaled font size
  205. *
  206. * @param float $size The font size (in points)
  207. *
  208. * @return void
  209. *
  210. * @see TCPDF::SetFontSize()
  211. */
  212. public function setFontSizeScale($size)
  213. {
  214. // Set font size in points
  215. $size /= $this->scale;
  216. $this->SetFontSize($size);
  217. }
  218. /**
  219. * Sets the scaled line width
  220. *
  221. * @param float $width The line width
  222. *
  223. * @return void
  224. *
  225. * @see TCPDF::SetLineWidth()
  226. */
  227. public function setLineWidthScale($width)
  228. {
  229. $width /= $this->scale;
  230. $this->SetLineWidth($width);
  231. }
  232. /**
  233. * This method is used to render the page header.
  234. *
  235. * @return void
  236. *
  237. * @see TCPDF::Header()
  238. */
  239. // @codingStandardsIgnoreLine
  240. public function Header()
  241. {
  242. // We only show this if we find something in the new pdf_pages table
  243. // This function must be named "Header" to work with the TCPDF library
  244. if ($this->_withDoc) {
  245. if ($this->_offline || $this->_pageNumber == -1) {
  246. $pg_name = __("PDF export page");
  247. } else {
  248. $test_query = 'SELECT * FROM '
  249. . Util::backquote($GLOBALS['cfgRelation']['db']) . '.'
  250. . Util::backquote($GLOBALS['cfgRelation']['pdf_pages'])
  251. . ' WHERE db_name = \'' . $GLOBALS['dbi']->escapeString($this->_db)
  252. . '\' AND page_nr = \'' . $this->_pageNumber . '\'';
  253. $test_rs = $this->relation->queryAsControlUser($test_query);
  254. $pages = @$GLOBALS['dbi']->fetchAssoc($test_rs);
  255. $pg_name = ucfirst($pages['page_descr']);
  256. }
  257. $this->SetFont($this->_ff, 'B', 14);
  258. $this->Cell(0, 6, $pg_name, 'B', 1, 'C');
  259. $this->SetFont($this->_ff, '');
  260. $this->Ln();
  261. }
  262. }
  263. /**
  264. * This function must be named "Footer" to work with the TCPDF library
  265. *
  266. * @return void
  267. *
  268. * @see PDF::Footer()
  269. */
  270. // @codingStandardsIgnoreLine
  271. public function Footer()
  272. {
  273. if ($this->_withDoc) {
  274. parent::Footer();
  275. }
  276. }
  277. /**
  278. * Sets widths
  279. *
  280. * @param array $w array of widths
  281. *
  282. * @return void
  283. */
  284. public function setWidths(array $w)
  285. {
  286. // column widths
  287. $this->widths = $w;
  288. }
  289. /**
  290. * Generates table row.
  291. *
  292. * @param array $data Data for table
  293. * @param array $links Links for table cells
  294. *
  295. * @return void
  296. */
  297. public function row(array $data, array $links)
  298. {
  299. // line height
  300. $nb = 0;
  301. $data_cnt = count($data);
  302. for ($i = 0; $i < $data_cnt; $i++) {
  303. $nb = max($nb, $this->numLines($this->widths[$i], $data[$i]));
  304. }
  305. $il = $this->FontSize;
  306. $h = ($il + 1) * $nb;
  307. // page break if necessary
  308. $this->checkPageBreak($h);
  309. // draw the cells
  310. $data_cnt = count($data);
  311. for ($i = 0; $i < $data_cnt; $i++) {
  312. $w = $this->widths[$i];
  313. // save current position
  314. $x = $this->GetX();
  315. $y = $this->GetY();
  316. // draw the border
  317. $this->Rect($x, $y, $w, $h);
  318. if (isset($links[$i])) {
  319. $this->Link($x, $y, $w, $h, $links[$i]);
  320. }
  321. // print text
  322. $this->MultiCell($w, $il + 1, $data[$i], 0, 'L');
  323. // go to right side
  324. $this->SetXY($x + $w, $y);
  325. }
  326. // go to line
  327. $this->Ln($h);
  328. }
  329. /**
  330. * Compute number of lines used by a multicell of width w
  331. *
  332. * @param int $w width
  333. * @param string $txt text
  334. *
  335. * @return int
  336. */
  337. public function numLines($w, $txt)
  338. {
  339. $cw = &$this->CurrentFont['cw'];
  340. if ($w == 0) {
  341. $w = $this->w - $this->rMargin - $this->x;
  342. }
  343. $wmax = ($w - 2 * $this->cMargin) * 1000 / $this->FontSize;
  344. $s = str_replace("\r", '', $txt);
  345. $nb = strlen($s);
  346. if ($nb > 0 && $s[$nb - 1] == "\n") {
  347. $nb--;
  348. }
  349. $sep = -1;
  350. $i = 0;
  351. $j = 0;
  352. $l = 0;
  353. $nl = 1;
  354. while ($i < $nb) {
  355. $c = $s[$i];
  356. if ($c == "\n") {
  357. $i++;
  358. $sep = -1;
  359. $j = $i;
  360. $l = 0;
  361. $nl++;
  362. continue;
  363. }
  364. if ($c == ' ') {
  365. $sep = $i;
  366. }
  367. $l += isset($cw[mb_ord($c)]) ? $cw[mb_ord($c)] : 0 ;
  368. if ($l > $wmax) {
  369. if ($sep == -1) {
  370. if ($i == $j) {
  371. $i++;
  372. }
  373. } else {
  374. $i = $sep + 1;
  375. }
  376. $sep = -1;
  377. $j = $i;
  378. $l = 0;
  379. $nl++;
  380. } else {
  381. $i++;
  382. }
  383. }
  384. return $nl;
  385. }
  386. /**
  387. * Set whether the document is generated from client side DB
  388. *
  389. * @param string $value whether offline
  390. *
  391. * @return void
  392. *
  393. * @access private
  394. */
  395. public function setOffline($value)
  396. {
  397. $this->_offline = $value;
  398. }
  399. }