⚝
One Hat Cyber Team
⚝
Your IP:
192.168.31.6
Server IP:
192.168.1.11
Server:
Linux pams 6.1.0-29-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.123-1 (2025-01-02) x86_64
PHP Version:
8.2.28
Buat File
|
Buat Folder
Upload File
Eksekusi
Dir :
~
/
var
/
www
/
lppm
/
vendor
/
tecnickcom
/
tc-lib-pdf
/
src
/
Edit File: MetaInfo.php
<?php /** * MetaInfo.php * * @since 2002-08-03 * @category Library * @package Pdf * @author Nicola Asuni <info@tecnick.com> * @copyright 2002-2025 Nicola Asuni - Tecnick.com LTD * @license http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT) * @link https://github.com/tecnickcom/tc-lib-pdf * * This file is part of tc-lib-pdf software library. */ namespace Com\Tecnick\Pdf; use Com\Tecnick\Pdf\Exception as PdfException; /** * Com\Tecnick\Pdf\MetaInfo * * Meta Informaton PDF class * * @since 2002-08-03 * @category Library * @package Pdf * @author Nicola Asuni <info@tecnick.com> * @copyright 2002-2025 Nicola Asuni - Tecnick.com LTD * @license http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT) * @link https://github.com/tecnickcom/tc-lib-pdf * * @phpstan-import-type TViewerPref from Base * * @SuppressWarnings("PHPMD.DepthOfInheritance") */ abstract class MetaInfo extends \Com\Tecnick\Pdf\JavaScript { /** * Valid document zoom modes * * @var array<string> */ protected const VALIDZOOM = ['fullpage', 'fullwidth', 'real', 'default']; /** * Return the program version. */ public function getVersion(): string { return $this->version; } /** * Set a field value only if it is not empty. * * @param string $field Field name * @param string $value Value to set */ private function setNonEmptyFieldValue(string $field, string $value): static { if ($value !== '') { $this->$field = $value; } return $this; } /** * Set the value of an existing array key if it is not empty. * * @param string $field Field array name * @param string $key Key name * @param string $value Value to set */ private function setNonEmptyArrayFieldValue(string $field, string $key, string $value): static { if ( isset($this->$field) && is_array($this->$field) && ($key !== '') && isset($this->$field[$key]) && ($value !== '') ) { $this->$field[$key] = $value; } return $this; } /** * Defines the creator of the document. * This is typically the name of the application that generates the PDF. * * @param string $creator The name of the creator. */ public function setCreator(string $creator): static { return $this->setNonEmptyFieldValue('creator', $creator); } /** * Defines the author of the document. * * @param string $author The name of the author. */ public function setAuthor(string $author): static { return $this->setNonEmptyFieldValue('author', $author); } /** * Defines the subject of the document. * * @param string $subject The subject. */ public function setSubject(string $subject): static { return $this->setNonEmptyFieldValue('subject', $subject); } /** * Defines the title of the document. * * @param string $title The title. */ public function setTitle(string $title): static { return $this->setNonEmptyFieldValue('title', $title); } /** * Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'. * * @param string $keywords Space-separated list of keywords. */ public function setKeywords(string $keywords): static { return $this->setNonEmptyFieldValue('keywords', $keywords); } /** * Set the PDF version (check PDF reference for valid values). * * @param string $version PDF document version. * * @throw PdfException in case of error. */ public function setPDFVersion(string $version = '1.7'): static { if ($this->pdfa == 1) { // PDF/A 1 mode $this->pdfver = '1.4'; return $this; } $isvalid = preg_match('/^[1-9]+[.]\d+$/', $version); if ($isvalid === false) { throw new PdfException('Invalid PDF version format'); } $this->pdfver = $version; return $this; } /** * Set the sRGB mode * * @param bool $enabled Set to true to add the default sRGB ICC color profile */ public function setSRGB(bool $enabled): static { $this->sRGB = $enabled; return $this; } /** * Format a text string for output. * * @param string $str String to escape. * @param int $oid Current PDF object number. * @param bool $bom If true set the Byte Order Mark (BOM). * * @return string escaped string. */ protected function getOutTextString( string $str, int $oid, bool $bom = false ): string { if ($this->isunicode) { $str = $this->uniconv->toUTF16BE($str); if ($bom) { $str = "\xFE\xFF" . $str; // Byte Order Mark (BOM) } } return $this->encrypt->escapeDataString($str, $oid); } /** * Returns a formatted date for meta information * * @param int $time Time in seconds. * * @return string date-time string. */ protected function getFormattedDate(int $time): string { return substr_replace(date('YmdHisO', $time), "'", (-2), 0) . "'"; } /** * Returns a formatted date for XMP meta information * * @param int $time Time in seconds. * * @return string date-time string. */ protected function getXMPFormattedDate(int $time): string { return date('Y-m-dTH:i:sP', $time); } /** * Returns the producer string */ protected function getProducer(): string { return "\x54\x43\x50\x44\x46\x20" . $this->version . "\x20\x28\x68\x74\x74\x70\x73\x3a\x2f\x2f" . "\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29"; } /** * Returns a formatted date for meta information * * @param int $time Time in seconds. * @param int $oid Current PDF object number. * * @return string escaped date-time string. */ protected function getOutDateTimeString(int $time, int $oid): string { if ($time === 0) { $time = $this->doctime; } return $this->encrypt->escapeDataString('D:' . $this->getFormattedDate($time), $oid); } /** * Get the PDF output string for the Document Information Dictionary. * (ref. Chapter 14.3.3 Document Information Dictionary of PDF32000_2008.pdf) */ protected function getOutMetaInfo(): string { $oid = ++$this->pon; $this->objid['info'] = $oid; return $oid . ' 0 obj' . "\n" . '<<' . ' /Creator ' . $this->getOutTextString($this->creator, $oid, true) . ' /Author ' . $this->getOutTextString($this->author, $oid, true) . ' /Subject ' . $this->getOutTextString($this->subject, $oid, true) . ' /Title ' . $this->getOutTextString($this->title, $oid, true) . ' /Keywords ' . $this->getOutTextString($this->keywords, $oid, true) . ' /Producer ' . $this->getOutTextString($this->getProducer(), $oid, true) . ' /CreationDate ' . $this->getOutDateTimeString($this->doctime, $oid) . ' /ModDate ' . $this->getOutDateTimeString($this->docmodtime, $oid) . ' /Trapped /False' . ' >>' . "\n" . 'endobj' . "\n"; } /** * Escape some special characters (< > &) for XML output. * * @param string $str Input string to escape. */ protected function getEscapedXML(string $str): string { return strtr($str, [ "\0" => '', '&' => '&', '<' => '<', '>' => '>', ]); } /** * Set additional custom XMP data to be appended just before the end of the tag indicated by the key. * * IMPORTANT: * This data is added as-is without controls, so you have to validate your data before using this method. * * @param string $key Key for the custom XMP data. Valid keys are: * - 'x:xmpmeta' * - 'x:xmpmeta.rdf:RDF' * - 'x:xmpmeta.rdf:RDF.rdf:Description' * - 'x:xmpmeta.rdf:RDF.rdf:Description.pdfaExtension:schemas' * - 'x:xmpmeta.rdf:RDF.rdf:Description.pdfaExtension:schemas.rdf:Bag' * @param string $xmp Custom XMP data. */ public function setCustomXMP(string $key, string $xmp): static { return $this->setNonEmptyArrayFieldValue('custom_xmp', $key, $xmp); } /** * Get the PDF output string for the XMP data object * * @SuppressWarnings("PHPMD.ExcessiveMethodLength") */ protected function getOutXMP(): string { $uuid = 'uuid:' . substr($this->fileid, 0, 8) . '-' . substr($this->fileid, 8, 4) . '-' . substr($this->fileid, 12, 4) . '-' . substr($this->fileid, 16, 4) . '-' . substr($this->fileid, 20, 12); // @codingStandardsIgnoreStart $xmp = '<?xpacket begin="' . $this->uniconv->chr(0xfeff) . '" id="W5M0MpCehiHzreSzNTczkc9d"?>' . "\n" . '<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:08:04">' . "\n" . "\t" . '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">' . "\n" . "\t\t" . '<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">' . "\n" . "\t\t\t" . '<dc:format>application/pdf</dc:format>' . "\n" . "\t\t\t" . '<dc:title>' . "\n" . "\t\t\t\t" . '<rdf:Alt>' . "\n" . "\t\t\t\t\t" . '<rdf:li xml:lang="x-default">' . $this->getEscapedXML($this->title) . '</rdf:li>' . "\n" . "\t\t\t\t" . '</rdf:Alt>' . "\n" . "\t\t\t" . '</dc:title>' . "\n" . "\t\t\t" . '<dc:creator>' . "\n" . "\t\t\t\t" . '<rdf:Seq>' . "\n" . "\t\t\t\t\t" . '<rdf:li>' . $this->getEscapedXML($this->author) . '</rdf:li>' . "\n" . "\t\t\t\t" . '</rdf:Seq>' . "\n" . "\t\t\t" . '</dc:creator>' . "\n" . "\t\t\t" . '<dc:description>' . "\n" . "\t\t\t\t" . '<rdf:Alt>' . "\n" . "\t\t\t\t\t" . '<rdf:li xml:lang="x-default">' . $this->getEscapedXML($this->subject) . '</rdf:li>' . "\n" . "\t\t\t\t" . '</rdf:Alt>' . "\n" . "\t\t\t" . '</dc:description>' . "\n" . "\t\t\t" . '<dc:subject>' . "\n" . "\t\t\t\t" . '<rdf:Bag>' . "\n" . "\t\t\t\t\t" . '<rdf:li>' . $this->getEscapedXML($this->keywords) . '</rdf:li>' . "\n" . "\t\t\t\t" . '</rdf:Bag>' . "\n" . "\t\t\t" . '</dc:subject>' . "\n" . "\t\t" . '</rdf:Description>' . "\n" . "\t\t" . '<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">' . "\n" . "\t\t\t" . '<xmp:CreateDate>' . $this->getXMPFormattedDate($this->doctime) . '</xmp:CreateDate>' . "\n" . "\t\t\t" . '<xmp:CreatorTool>' . $this->getEscapedXML($this->creator) . '</xmp:CreatorTool>' . "\n" . "\t\t\t" . '<xmp:ModifyDate>' . $this->getXMPFormattedDate($this->docmodtime) . '</xmp:ModifyDate>' . "\n" . "\t\t\t" . '<xmp:MetadataDate>' . $this->getXMPFormattedDate($this->doctime) . '</xmp:MetadataDate>' . "\n" . "\t\t" . '</rdf:Description>' . "\n" . "\t\t" . '<rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">' . "\n" . "\t\t\t" . '<pdf:Keywords>' . $this->getEscapedXML($this->keywords) . '</pdf:Keywords>' . "\n" . "\t\t\t" . '<pdf:Producer>' . $this->getEscapedXML($this->getProducer()) . '</pdf:Producer>' . "\n" . "\t\t" . '</rdf:Description>' . "\n" . "\t\t" . '<rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">' . "\n" . "\t\t\t" . '<xmpMM:DocumentID>' . $uuid . '</xmpMM:DocumentID>' . "\n" . "\t\t\t" . '<xmpMM:InstanceID>' . $uuid . '</xmpMM:InstanceID>' . "\n" . "\t\t" . '</rdf:Description>' . "\n"; if ($this->pdfa !== 0) { $xmp .= ' <rdf:Description rdf:about="" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/">' . "\n" . "\t\t\t" . '<pdfaid:part>' . $this->pdfa . '</pdfaid:part>' . "\n" . "\t\t\t" . '<pdfaid:conformance>B</pdfaid:conformance>' . "\n" . "\t\t" . '</rdf:Description>' . "\n"; } // XMP extension schemas $xmp .= "\t\t" . '<rdf:Description rdf:about="" xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/" xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#" xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">' . "\n" . "\t\t\t" . '<pdfaExtension:schemas>' . "\n" . "\t\t\t\t" . '<rdf:Bag>' . "\n" . "\t\t\t\t\t" . '<rdf:li rdf:parseType="Resource">' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:namespaceURI>http://ns.adobe.com/pdf/1.3/</pdfaSchema:namespaceURI>' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:prefix>pdf</pdfaSchema:prefix>' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:schema>Adobe PDF Schema</pdfaSchema:schema>' . "\n" . "\t\t\t\t\t" . '</rdf:li>' . "\n" . "\t\t\t\t\t" . '<rdf:li rdf:parseType="Resource">' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:namespaceURI>http://ns.adobe.com/xap/1.0/mm/</pdfaSchema:namespaceURI>' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:prefix>xmpMM</pdfaSchema:prefix>' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:schema>XMP Media Management Schema</pdfaSchema:schema>' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:property>' . "\n" . "\t\t\t\t\t\t\t" . '<rdf:Seq>' . "\n" . "\t\t\t\t\t\t\t\t" . '<rdf:li rdf:parseType="Resource">' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:category>internal</pdfaProperty:category>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:description>UUID based identifier for specific incarnation of a document</pdfaProperty:description>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:name>InstanceID</pdfaProperty:name>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:valueType>URI</pdfaProperty:valueType>' . "\n" . "\t\t\t\t\t\t\t\t" . '</rdf:li>' . "\n" . "\t\t\t\t\t\t\t" . '</rdf:Seq>' . "\n" . "\t\t\t\t\t\t" . '</pdfaSchema:property>' . "\n" . "\t\t\t\t\t" . '</rdf:li>' . "\n" . "\t\t\t\t\t" . '<rdf:li rdf:parseType="Resource">' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:namespaceURI>http://www.aiim.org/pdfa/ns/id/</pdfaSchema:namespaceURI>' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:prefix>pdfaid</pdfaSchema:prefix>' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:schema>PDF/A ID Schema</pdfaSchema:schema>' . "\n" . "\t\t\t\t\t\t" . '<pdfaSchema:property>' . "\n" . "\t\t\t\t\t\t\t" . '<rdf:Seq>' . "\n" . "\t\t\t\t\t\t\t\t" . '<rdf:li rdf:parseType="Resource">' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:category>internal</pdfaProperty:category>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:description>Part of PDF/A standard</pdfaProperty:description>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:name>part</pdfaProperty:name>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:valueType>Integer</pdfaProperty:valueType>' . "\n" . "\t\t\t\t\t\t\t\t" . '</rdf:li>' . "\n" . "\t\t\t\t\t\t\t\t" . '<rdf:li rdf:parseType="Resource">' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:category>internal</pdfaProperty:category>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:description>Amendment of PDF/A standard</pdfaProperty:description>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:name>amd</pdfaProperty:name>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:valueType>Text</pdfaProperty:valueType>' . "\n" . "\t\t\t\t\t\t\t\t" . '</rdf:li>' . "\n" . "\t\t\t\t\t\t\t\t" . '<rdf:li rdf:parseType="Resource">' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:category>internal</pdfaProperty:category>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:description>Conformance level of PDF/A standard</pdfaProperty:description>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:name>conformance</pdfaProperty:name>' . "\n" . "\t\t\t\t\t\t\t\t\t" . '<pdfaProperty:valueType>Text</pdfaProperty:valueType>' . "\n" . "\t\t\t\t\t\t\t\t" . '</rdf:li>' . "\n" . "\t\t\t\t\t\t\t" . '</rdf:Seq>' . "\n" . "\t\t\t\t\t\t" . '</pdfaSchema:property>' . "\n" . "\t\t\t\t\t" . '</rdf:li>' . "\n" . $this->custom_xmp['x:xmpmeta.rdf:RDF.rdf:Description.pdfaExtension:schemas.rdf:Bag'] . "\n" . "\t\t\t\t" . '</rdf:Bag>' . "\n" . $this->custom_xmp['x:xmpmeta.rdf:RDF.rdf:Description.pdfaExtension:schemas'] . "\n" . "\t\t\t" . '</pdfaExtension:schemas>' . "\n" . $this->custom_xmp['x:xmpmeta.rdf:RDF.rdf:Description'] . "\n" . "\t\t" . '</rdf:Description>' . "\n" . $this->custom_xmp['x:xmpmeta.rdf:RDF'] . "\n" . "\t" . '</rdf:RDF>' . "\n" . $this->custom_xmp['x:xmpmeta'] . "\n" . '</x:xmpmeta>' . "\n" . '<?xpacket end="w"?>'; // @codingStandardsIgnoreEnd $oid = ++$this->pon; $this->objid['xmp'] = $oid; return $oid . ' 0 obj' . "\n" . '<<' . ' /Type /Metadata' . ' /Subtype /XML' . ' /Length ' . strlen($xmp) . ' >> stream' . "\n" . $xmp . "\n" . 'endstream' . "\n" . 'endobj' . "\n"; } /** * Set the default document language direction. * * @param bool $enabled False = LTR = Left-To-Right; True = RTL = Right-To-Left. */ public function setRTL(bool $enabled): static { $this->rtl = $enabled; return $this; } /** * Set the viewer preferences dictionary * controlling the way the document is to be presented on the screen or in print. * * @param TViewerPref $pref Array of options (see PDF reference "Viewer Preferences"). */ public function setViewerPreferences(array $pref): static { $this->viewerpref = $pref; return $this; } /** * Sanitize the page box name and return the default 'CropBox' in case of error. * * @param string $name Entry name. */ protected function getPageBoxName(string $name): string { $box = 'CropBox'; if (isset($this->viewerpref[$name])) { $val = $this->viewerpref[$name]; if ( isset($this->page->$box[$val]) // @phpstan-ignore offsetAccess.nonOffsetAccessible && is_string($this->page->$box[$val]) ) { $box = $this->page->$box[$val]; } } return ' /' . $name . ' /' . $box; } /** * Sanitize the page box name and return the default 'CropBox' in case of error. */ protected function getPagePrintScaling(): string { $mode = 'AppDefault'; if (isset($this->viewerpref['PrintScaling'])) { $name = strtolower($this->viewerpref['PrintScaling']); $valid = [ 'none' => 'None', 'appdefault' => 'AppDefault', ]; if (isset($valid[$name])) { $mode = $valid[$name]; } } return ' /PrintScaling /' . $mode; } /** * Returns the Duplex mode for the Viewer Preferences */ protected function getDuplexMode(): string { if (isset($this->viewerpref['Duplex'])) { $name = strtolower($this->viewerpref['Duplex']); $valid = [ 'simplex' => 'Simplex', 'duplexflipshortedge' => 'DuplexFlipShortEdge', 'duplexfliplongedge' => 'DuplexFlipLongEdge', ]; if (isset($valid[$name])) { return ' /Duplex /' . $valid[$name]; } } return ''; } /** * Returns the Viewer Preference boolean entry. * * @param string $name Entry name. */ protected function getBooleanMode(string $name): string { if (isset($this->viewerpref[$name])) { return ' /' . $name . ' ' . ($this->viewerpref[$name] === true ? 'true' : 'false'); } return ''; } /** * Returns the PDF viewer preferences for the catalog section */ protected function getOutViewerPref(): string { $vpr = $this->viewerpref; $out = ' /ViewerPreferences <<'; if ($this->rtl) { $out .= ' /Direction /R2L'; } else { $out .= ' /Direction /L2R'; } $out .= $this->getBooleanMode('HideToolbar'); $out .= $this->getBooleanMode('HideMenubar'); $out .= $this->getBooleanMode('HideWindowUI'); $out .= $this->getBooleanMode('FitWindow'); $out .= $this->getBooleanMode('CenterWindow'); $out .= $this->getBooleanMode('DisplayDocTitle'); if (isset($vpr['NonFullScreenPageMode'])) { $out .= ' /NonFullScreenPageMode /' . $this->page->getDisplay($vpr['NonFullScreenPageMode']); } $out .= $this->getPageBoxName('ViewArea'); $out .= $this->getPageBoxName('ViewClip'); $out .= $this->getPageBoxName('PrintArea'); $out .= $this->getPageBoxName('PrintClip'); $out .= $this->getPagePrintScaling(); $out .= $this->getDuplexMode(); $out .= $this->getBooleanMode('PickTrayByPDFSize'); if (isset($vpr['PrintPageRange'])) { $PrintPageRangeNum = ''; foreach ($vpr['PrintPageRange'] as $pnum) { $PrintPageRangeNum .= ' ' . ($pnum - 1) . ''; } $out .= ' /PrintPageRange [' . $PrintPageRangeNum . ' ]'; } if (isset($vpr['NumCopies'])) { $out .= ' /NumCopies ' . (int) $vpr['NumCopies']; } return $out . ' >>'; } }
Simpan