diff --git a/mod/assign/feedback/editpdf/fpdi/FpdfTpl.php b/mod/assign/feedback/editpdf/fpdi/FpdfTpl.php index a1bfdedec59..4b93f5396f2 100644 --- a/mod/assign/feedback/editpdf/fpdi/FpdfTpl.php +++ b/mod/assign/feedback/editpdf/fpdi/FpdfTpl.php @@ -1,9 +1,10 @@ _getpagesize($size); - if ($orientation != $this->CurOrientation + if ( + $orientation != $this->CurOrientation || $size[0] != $this->CurPageSize[0] || $size[1] != $this->CurPageSize[1] ) { @@ -109,7 +109,7 @@ trait FpdfTplTrait unset($x['tpl']); \extract($x, EXTR_IF_EXISTS); /** @noinspection NotOptimalIfConditionsInspection */ - /** @noinspection CallableParameterUseCaseInTypeContextInspection */ + /** @noinspection PhpConditionAlreadyCheckedInspection */ if (\is_array($x)) { $x = 0; } @@ -266,7 +266,7 @@ trait FpdfTplTrait */ public function endTemplate() { - if (null === $this->currentTemplateId) { + if ($this->currentTemplateId === null) { return false; } @@ -418,7 +418,11 @@ trait FpdfTplTrait $this->templates[$key]['objectNumber'] = $this->n; $this->_put('<_put(\sprintf('/BBox[0 0 %.2F %.2F]', $template['width'] * $this->k, $template['height'] * $this->k)); + $this->_put(\sprintf( + '/BBox[0 0 %.2F %.2F]', + $template['width'] * $this->k, + $template['height'] * $this->k + )); $this->_put('/Resources 2 0 R'); // default resources dictionary of FPDF if ($this->compress) { @@ -463,4 +467,4 @@ trait FpdfTplTrait parent::_out($s); } } -} \ No newline at end of file +} diff --git a/mod/assign/feedback/editpdf/fpdi/Fpdi.php b/mod/assign/feedback/editpdf/fpdi/Fpdi.php index b49c103bb0d..1eafa9a37e1 100644 --- a/mod/assign/feedback/editpdf/fpdi/Fpdi.php +++ b/mod/assign/feedback/editpdf/fpdi/Fpdi.php @@ -1,9 +1,10 @@ objectsToCopy[$readerId])) !== null) { try { $object = $parser->getIndirectObject($objectNumber); - } catch (CrossReferenceException $e) { if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); diff --git a/mod/assign/feedback/editpdf/fpdi/FpdiException.php b/mod/assign/feedback/editpdf/fpdi/FpdiException.php index d126c14f0e3..22866674410 100644 --- a/mod/assign/feedback/editpdf/fpdi/FpdiException.php +++ b/mod/assign/feedback/editpdf/fpdi/FpdiException.php @@ -1,9 +1,10 @@ readers[$id]); } - $this->createdReaders= []; + $this->createdReaders = []; } /** @@ -128,6 +127,9 @@ trait FpdiTrait */ protected function getPdfParserInstance(StreamReader $streamReader) { + // note: if you get an exception here - turn off errors/warnings on not found for your autoloader. + // psr-4 (https://www.php-fig.org/psr/psr-4/) says: Autoloader implementations MUST NOT throw + // exceptions, MUST NOT raise errors of any level, and SHOULD NOT return a value. /** @noinspection PhpUndefinedClassInspection */ if (\class_exists(FpdiPdfParser::class)) { /** @noinspection PhpUndefinedClassInspection */ @@ -299,7 +301,7 @@ trait FpdiTrait if ($rotation !== 0) { $rotation *= -1; - $angle = $rotation * M_PI/180; + $angle = $rotation * M_PI / 180; $a = \cos($angle); $b = \sin($angle); $c = -$b; @@ -336,7 +338,8 @@ trait FpdiTrait $contents = PdfType::resolve($contentsObject, $reader->getParser()); // just copy the stream reference if it is only a single stream - if (($contentsIsStream = ($contents instanceof PdfStream)) + if ( + ($contentsIsStream = ($contents instanceof PdfStream)) || ($contents instanceof PdfArray && \count($contents->value) === 1) ) { if ($contentsIsStream) { @@ -494,26 +497,20 @@ trait FpdiTrait } else { $this->_put(\rtrim(\rtrim(\sprintf('%.5F', $value->value), '0'), '.') . ' ', false); } - } elseif ($value instanceof PdfName) { $this->_put('/' . $value->value . ' ', false); - } elseif ($value instanceof PdfString) { $this->_put('(' . $value->value . ')', false); - } elseif ($value instanceof PdfHexString) { $this->_put('<' . $value->value . '>'); - } elseif ($value instanceof PdfBoolean) { $this->_put($value->value ? 'true ' : 'false ', false); - } elseif ($value instanceof PdfArray) { $this->_put('[', false); foreach ($value->value as $entry) { $this->writePdfType($entry); } $this->_put(']'); - } elseif ($value instanceof PdfDictionary) { $this->_put('<<', false); foreach ($value->value as $name => $entry) { @@ -521,13 +518,10 @@ trait FpdiTrait $this->writePdfType($entry); } $this->_put('>>'); - } elseif ($value instanceof PdfToken) { $this->_put($value->value); - } elseif ($value instanceof PdfNull) { $this->_put('null '); - } elseif ($value instanceof PdfStream) { /** * @var $value PdfStream @@ -536,7 +530,6 @@ trait FpdiTrait $this->_put('stream'); $this->_put($value->getStream()); $this->_put('endstream'); - } elseif ($value instanceof PdfIndirectObjectReference) { if (!isset($this->objectMap[$this->currentReaderId])) { $this->objectMap[$this->currentReaderId] = []; @@ -548,10 +541,9 @@ trait FpdiTrait } $this->_put($this->objectMap[$this->currentReaderId][$value->value] . ' 0 R ', false); - } elseif ($value instanceof PdfIndirectObject) { /** - * @var $value PdfIndirectObject + * @var PdfIndirectObject $value */ $n = $this->objectMap[$this->currentReaderId][$value->objectNumber]; $this->_newobj($n); diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/AbstractReader.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/AbstractReader.php index 1d5c579563b..b54237bc1d3 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/AbstractReader.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/AbstractReader.php @@ -1,9 +1,10 @@ parser->getStreamReader()->reset($offset); $this->parser->getTokenizer()->clearStack(); $initValue = $this->parser->readValue(); - + return $this->initReaderInstance($initValue); } @@ -235,8 +234,15 @@ class CrossReference } if ($initValue instanceof PdfIndirectObject) { - // check for encryption - $stream = PdfStream::ensure($initValue->value); + try { + $stream = PdfStream::ensure($initValue->value); + } catch (PdfTypeException $e) { + throw new CrossReferenceException( + 'Invalid object type at xref reference offset.', + CrossReferenceException::INVALID_DATA, + $e + ); + } $type = PdfDictionary::get($stream->value, 'Type'); if ($type->value !== 'XRef') { diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/CrossReferenceException.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/CrossReferenceException.php index 3fa9b33a765..7d88d5d05b5 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/CrossReferenceException.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/CrossReferenceException.php @@ -1,9 +1,10 @@ subSections as $offset => list($startObject, $objectCount)) { + /** + * @var int $startObject + * @var int $objectCount + */ if ($objectNumber >= $startObject && $objectNumber < ($startObject + $objectCount)) { $position = $offset + 20 * ($objectNumber - $startObject); $this->reader->ensure($position, 20); diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/LineReader.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/LineReader.php index 31a96be9670..b6f0e421172 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/LineReader.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/LineReader.php @@ -1,9 +1,10 @@ 20 bytes). - * - * @package setasign\Fpdi\PdfParser\CrossReference */ class LineReader extends AbstractReader implements ReaderInterface { @@ -72,18 +71,16 @@ class LineReader extends AbstractReader implements ReaderInterface */ protected function extract(StreamReader $reader) { - $cycles = -1; $bytesPerCycle = 100; - $reader->reset(null, $bytesPerCycle); - while ( - ($trailerPos = \strpos($reader->getBuffer(false), 'trailer', \max($bytesPerCycle * $cycles++, 0))) === false - ) { - if ($reader->increaseLength($bytesPerCycle) === false) { - break; - } - } + $cycles = 0; + do { + // 6 = length of "trailer" - 1 + $pos = \max(($bytesPerCycle * $cycles) - 6, 0); + $trailerPos = \strpos($reader->getBuffer(false), 'trailer', $pos); + $cycles++; + } while ($trailerPos === false && $reader->increaseLength($bytesPerCycle) !== false); if ($trailerPos === false) { throw new CrossReferenceException( @@ -127,44 +124,41 @@ class LineReader extends AbstractReader implements ReaderInterface } unset($differentLineEndings, $m); - $linesCount = \count($lines); - $start = null; - $entryCount = 0; + if (!\is_array($lines)) { + $this->offsets = []; + return; + } + $start = 0; $offsets = []; - /** @noinspection ForeachInvariantsInspection */ - for ($i = 0; $i < $linesCount; $i++) { - $line = \trim($lines[$i]); - if ($line) { - $pieces = \explode(' ', $line); + // trim all lines and remove empty lines + $lines = \array_filter(\array_map('\trim', $lines)); + foreach ($lines as $line) { + $pieces = \explode(' ', $line); - $c = \count($pieces); - switch ($c) { - case 2: - $start = (int) $pieces[0]; - $entryCount += (int) $pieces[1]; - break; + switch (\count($pieces)) { + case 2: + $start = (int) $pieces[0]; + break; - /** @noinspection PhpMissingBreakStatementInspection */ - case 3: - switch ($pieces[2]) { - case 'n': - $offsets[$start] = [(int) $pieces[0], (int) $pieces[1]]; - $start++; - break 2; - case 'f': - $start++; - break 2; - } - // fall through if pieces doesn't match + case 3: + switch ($pieces[2]) { + case 'n': + $offsets[$start] = [(int) $pieces[0], (int) $pieces[1]]; + $start++; + break 2; + case 'f': + $start++; + break 2; + } + // fall through if pieces doesn't match - default: - throw new CrossReferenceException( - \sprintf('Unexpected data in xref table (%s)', \implode(' ', $pieces)), - CrossReferenceException::INVALID_DATA - ); - } + default: + throw new CrossReferenceException( + \sprintf('Unexpected data in xref table (%s)', \implode(' ', $pieces)), + CrossReferenceException::INVALID_DATA + ); } } diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/ReaderInterface.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/ReaderInterface.php index 84b22679ee6..d2dfdd0c944 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/ReaderInterface.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/CrossReference/ReaderInterface.php @@ -1,9 +1,10 @@ 117 /* u */) { throw new Ascii85Exception( 'Illegal character found while ASCII85 decode.', @@ -86,12 +86,10 @@ class Ascii85 implements FilterInterface if ($state === 2) { $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1] + 1) * 85 * 85 * 85; $out .= \chr($r >> 24); - } elseif ($state === 3) { $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2] + 1) * 85 * 85; $out .= \chr($r >> 24); $out .= \chr($r >> 16); - } elseif ($state === 4) { $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3] + 1) * 85; $out .= \chr($r >> 24); diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/Ascii85Exception.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/Ascii85Exception.php index 898276c7c26..f4b675837e4 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/Ascii85Exception.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/Ascii85Exception.php @@ -1,9 +1,10 @@ extensionLoaded()) { $oData = $data; - $data = @((\strlen($data) > 0) ? \gzuncompress($data) : ''); + $data = (($data !== '') ? @\gzuncompress($data) : ''); if ($data === false) { + // let's try if the checksum is CRC32 + $fh = fopen('php://temp', 'w+b'); + fwrite($fh, "\x1f\x8b\x08\x00\x00\x00\x00\x00" . $oData); + stream_filter_append($fh, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 30]); + fseek($fh, 0); + $data = @stream_get_contents($fh); + fclose($fh); + + if ($data) { + return $data; + } + // Try this fallback - $tries = 1; - while ($tries < 10 && ($data === false || \strlen($data) < (\strlen($oData) - $tries - 1))) { - $data = @(\gzinflate(\substr($oData, $tries))); + $tries = 0; + + $oDataLen = strlen($oData); + while ($tries < 6 && ($data === false || (strlen($data) < ($oDataLen - $tries - 1)))) { + $data = @(gzinflate(substr($oData, $tries))); $tries++; } - if ($data === false) { - // let's try if the checksum is CRC32 - $fh = fopen('php://temp', 'w+b'); - \fwrite($fh, "\x1f\x8b\x08\x00\x00\x00\x00\x00" . $oData); - \stream_filter_append($fh, 'zlib.inflate', \STREAM_FILTER_READ, ['window' => 30]); - \fseek($fh, 0); - $data = \stream_get_contents($fh); - \fclose($fh); + // let's use this fallback only if the $data is longer than the original data + if (strlen($data) > ($oDataLen - $tries - 1)) { + return $data; } if (!$data) { diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/FlateException.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/FlateException.php index d44281da7be..d897ac8ee19 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/FlateException.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/FlateException.php @@ -1,9 +1,10 @@ sTable[$code]; $oldCode = $code; - } else { if ($code < $this->tIdx) { $string = $this->sTable[$code]; diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/LzwException.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/LzwException.php index e822bc98ea6..6ebad4f45fb 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/LzwException.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Filter/LzwException.php @@ -1,9 +1,10 @@ streamReader->reset(0); - $offset = false; $maxIterations = 1000; while (true) { $buffer = $this->streamReader->getBuffer(false); @@ -181,7 +180,10 @@ class PdfParser $catalog = $this->getCatalog(); if (isset($catalog->value['Version'])) { - $versionParts = \explode('.', PdfName::unescape(PdfType::resolve($catalog->value['Version'], $this)->value)); + $versionParts = \explode( + '.', + PdfName::unescape(PdfType::resolve($catalog->value['Version'], $this)->value) + ); if (count($versionParts) === 2) { list($major, $minor) = $versionParts; } @@ -200,8 +202,7 @@ class PdfParser */ public function getCatalog() { - $xref = $this->getCrossReference(); - $trailer = $xref->getTrailer(); + $trailer = $this->getCrossReference()->getTrailer(); $catalog = PdfType::resolve(PdfDictionary::get($trailer, 'Root'), $this); @@ -224,8 +225,7 @@ class PdfParser return $this->objects[$objectNumber]; } - $xref = $this->getCrossReference(); - $object = $xref->getIndirectObject($objectNumber); + $object = $this->getCrossReference()->getIndirectObject($objectNumber); if ($cache) { $this->objects[$objectNumber] = $object; @@ -239,7 +239,7 @@ class PdfParser * * @param null|bool|string $token * @param null|string $expectedType - * @return bool|PdfArray|PdfBoolean|PdfHexString|PdfName|PdfNull|PdfNumeric|PdfString|PdfToken|PdfIndirectObjectReference + * @return false|PdfArray|PdfBoolean|PdfDictionary|PdfHexString|PdfIndirectObject|PdfIndirectObjectReference|PdfName|PdfNull|PdfNumeric|PdfStream|PdfString|PdfToken * @throws Type\PdfTypeException */ public function readValue($token = null, $expectedType = null) @@ -281,37 +281,38 @@ class PdfParser default: if (\is_numeric($token)) { if (($token2 = $this->tokenizer->getNextToken()) !== false) { - if (\is_numeric($token2)) { - if (($token3 = $this->tokenizer->getNextToken()) !== false) { - switch ($token3) { - case 'obj': - if ($expectedType !== null && $expectedType !== PdfIndirectObject::class) { - throw new Type\PdfTypeException( - 'Got unexpected token type.', Type\PdfTypeException::INVALID_DATA_TYPE - ); - } - - return PdfIndirectObject::parse( - $token, - $token2, - $this, - $this->tokenizer, - $this->streamReader + if (\is_numeric($token2) && ($token3 = $this->tokenizer->getNextToken()) !== false) { + switch ($token3) { + case 'obj': + if ($expectedType !== null && $expectedType !== PdfIndirectObject::class) { + throw new Type\PdfTypeException( + 'Got unexpected token type.', + Type\PdfTypeException::INVALID_DATA_TYPE ); - case 'R': - if ($expectedType !== null && - $expectedType !== PdfIndirectObjectReference::class - ) { - throw new Type\PdfTypeException( - 'Got unexpected token type.', Type\PdfTypeException::INVALID_DATA_TYPE - ); - } + } - return PdfIndirectObjectReference::create($token, $token2); - } + return PdfIndirectObject::parse( + (int) $token, + (int) $token2, + $this, + $this->tokenizer, + $this->streamReader + ); + case 'R': + if ( + $expectedType !== null && + $expectedType !== PdfIndirectObjectReference::class + ) { + throw new Type\PdfTypeException( + 'Got unexpected token type.', + Type\PdfTypeException::INVALID_DATA_TYPE + ); + } - $this->tokenizer->pushStack($token3); + return PdfIndirectObjectReference::create((int) $token, (int) $token2); } + + $this->tokenizer->pushStack($token3); } $this->tokenizer->pushStack($token2); @@ -319,10 +320,11 @@ class PdfParser if ($expectedType !== null && $expectedType !== PdfNumeric::class) { throw new Type\PdfTypeException( - 'Got unexpected token type.', Type\PdfTypeException::INVALID_DATA_TYPE + 'Got unexpected token type.', + Type\PdfTypeException::INVALID_DATA_TYPE ); } - return PdfNumeric::create($token); + return PdfNumeric::create($token + 0); } if ($token === 'true' || $token === 'false') { @@ -337,7 +339,8 @@ class PdfParser if ($expectedType !== null && $expectedType !== PdfToken::class) { throw new Type\PdfTypeException( - 'Got unexpected token type.', Type\PdfTypeException::INVALID_DATA_TYPE + 'Got unexpected token type.', + Type\PdfTypeException::INVALID_DATA_TYPE ); } diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/PdfParserException.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/PdfParserException.php index 476bccd554c..6d034d86de7 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/PdfParserException.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/PdfParserException.php @@ -1,9 +1,10 @@ offset); - if ($position >= $this->bufferLength && - (!$this->increaseLength() || $position >= $this->bufferLength) + if ( + $position >= $this->bufferLength + && (!$this->increaseLength() || $position >= $this->bufferLength) ) { return false; } @@ -226,8 +226,9 @@ class StreamReader $offset = $this->offset; } - if ($offset >= $this->bufferLength && - ((!$this->increaseLength()) || $offset >= $this->bufferLength) + if ( + $offset >= $this->bufferLength + && ((!$this->increaseLength()) || $offset >= $this->bufferLength) ) { return false; } @@ -245,7 +246,7 @@ class StreamReader * * @param int $length * @param int|null $position - * @return string + * @return string|false */ public function readBytes($length, $position = null) { @@ -262,8 +263,9 @@ class StreamReader $offset = $this->offset; } - if (($offset + $length) > $this->bufferLength && - ((!$this->increaseLength($length)) || ($offset + $length) > $this->bufferLength) + if ( + ($offset + $length) > $this->bufferLength + && ((!$this->increaseLength($length)) || ($offset + $length) > $this->bufferLength) ) { return false; } @@ -433,7 +435,8 @@ class StreamReader */ public function ensure($pos, $length) { - if ($pos >= $this->position + if ( + $pos >= $this->position && $pos < ($this->position + $this->bufferLength) && ($this->position + $this->bufferLength) >= ($pos + $length) ) { diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Tokenizer.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Tokenizer.php index ebf0d0b882d..a3bcd01d907 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Tokenizer.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Tokenizer.php @@ -1,9 +1,10 @@ leapWhiteSpaces() === false) { return false; } diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfArray.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfArray.php index 9cf449ad88e..5d0bbbdad31 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfArray.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfArray.php @@ -1,9 +1,10 @@ value = $result; return $v; @@ -55,7 +55,7 @@ class PdfArray extends PdfType */ public static function create(array $values = []) { - $v = new self; + $v = new self(); $v->value = $values; return $v; diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfBoolean.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfBoolean.php index 5f746b7d406..ba4233a69c2 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfBoolean.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfBoolean.php @@ -1,9 +1,10 @@ value = (boolean) $value; + $v = new self(); + $v->value = (bool) $value; return $v; } diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfDictionary.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfDictionary.php index 46b669d6347..28188424594 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfDictionary.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfDictionary.php @@ -1,9 +1,10 @@ value] = $value; } - $v = new self; + $v = new self(); $v->value = $entries; return $v; @@ -93,7 +92,7 @@ class PdfDictionary extends PdfType */ public static function create(array $entries = []) { - $v = new self; + $v = new self(); $v->value = $entries; return $v; @@ -104,7 +103,7 @@ class PdfDictionary extends PdfType * * @param mixed $dictionary * @param string $key - * @param PdfType|mixed|null $default + * @param PdfType|null $default * @return PdfNull|PdfType * @throws PdfTypeException */ diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfHexString.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfHexString.php index 793fa43adcd..0084ada4d16 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfHexString.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfHexString.php @@ -1,9 +1,10 @@ getOffset(); - /** - * @var string $buffer - * @var int $pos - */ while (true) { $buffer = $streamReader->getBuffer(false); $pos = \strpos($buffer, '>', $bufferOffset); @@ -48,7 +43,7 @@ class PdfHexString extends PdfType $result = \substr($buffer, $bufferOffset, $pos - $bufferOffset); $streamReader->setOffset($pos + 1); - $v = new self; + $v = new self(); $v->value = $result; return $v; @@ -62,7 +57,7 @@ class PdfHexString extends PdfType */ public static function create($string) { - $v = new self; + $v = new self(); $v->value = $string; return $v; diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfIndirectObject.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfIndirectObject.php index a5bd2ac6625..15786d00cb8 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfIndirectObject.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfIndirectObject.php @@ -1,9 +1,10 @@ pushStack($nextToken); } - $v = new self; + $v = new self(); $v->objectNumber = (int) $objectNumberToken; $v->generationNumber = (int) $objectGenerationNumberToken; $v->value = $value; @@ -68,7 +67,7 @@ class PdfIndirectObject extends PdfType */ public static function create($objectNumber, $generationNumber, PdfType $value) { - $v = new self; + $v = new self(); $v->objectNumber = (int) $objectNumber; $v->generationNumber = (int) $generationNumber; $v->value = $value; diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfIndirectObjectReference.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfIndirectObjectReference.php index c6a67a0eff4..2725d0c977b 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfIndirectObjectReference.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfIndirectObjectReference.php @@ -1,9 +1,10 @@ value = (int) $objectNumber; $v->generationNumber = (int) $generationNumber; diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfName.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfName.php index 6be7d0e5123..194a13fe3c2 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfName.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfName.php @@ -1,9 +1,10 @@ getByte(), "\x00\x09\x0A\x0C\x0D\x20()<>[]{}/%") === 0) { $v->value = (string) $tokenizer->getNextToken(); return $v; @@ -44,13 +43,14 @@ class PdfName extends PdfType * @param string $value * @return string */ - static public function unescape($value) + public static function unescape($value) { - if (strpos($value, '#') === false) + if (strpos($value, '#') === false) { return $value; + } - return preg_replace_callback('/#[a-fA-F\d]{2}/', function($matches) { - return chr(hexdec($matches[0])); + return preg_replace_callback('/#([a-fA-F\d]{2})/', function ($matches) { + return chr(hexdec($matches[1])); }, $value); } @@ -62,7 +62,7 @@ class PdfName extends PdfType */ public static function create($string) { - $v = new self; + $v = new self(); $v->value = $string; return $v; diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfNull.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfNull.php index 3dbe37cc8c8..0c4c10826ab 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfNull.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfNull.php @@ -1,9 +1,10 @@ value = $value + 0; return $v; diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfStream.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfStream.php index 4b9300ba18d..6d4c5a8262c 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfStream.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfStream.php @@ -1,9 +1,10 @@ value = $dictionary; $v->reader = $reader; $v->parser = $parser; @@ -54,7 +53,7 @@ class PdfStream extends PdfType } } - if (false === $firstByte) { + if ($firstByte === false) { throw new PdfTypeException( 'Unable to parse stream data. No newline after the stream keyword found.', PdfTypeException::NO_NEWLINE_AFTER_STREAM_KEYWORD @@ -86,7 +85,7 @@ class PdfStream extends PdfType */ public static function create(PdfDictionary $dictionary, $stream) { - $v = new self; + $v = new self(); $v->value = $dictionary; $v->stream = (string) $stream; @@ -115,7 +114,7 @@ class PdfStream extends PdfType /** * The stream reader instance. * - * @var StreamReader + * @var StreamReader|null */ protected $reader; @@ -208,6 +207,13 @@ class PdfStream extends PdfType } } + // There are streams in the wild, which have only white signs in them but need to be parsed manually due + // to a problem encountered before (e.g. Length === 0). We should set them to empty streams to avoid problems + // in further processing (e.g. applying of filters). + if (trim($buffer) === '') { + $buffer = ''; + } + return $buffer; } diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfString.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfString.php index f933b1add6e..1636e68d60f 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfString.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfString.php @@ -1,9 +1,10 @@ setOffset($pos); - $v = new self; + $v = new self(); $v->value = $result; return $v; @@ -61,7 +60,7 @@ class PdfString extends PdfType */ public static function create($value) { - $v = new self; + $v = new self(); $v->value = $value; return $v; @@ -138,22 +137,23 @@ class PdfString extends PdfType $actualChar = \ord($s[$count]); // ascii 48 = number 0 // ascii 57 = number 9 - if ($actualChar >= 48 && - $actualChar <= 57) { + if ($actualChar >= 48 && $actualChar <= 57) { $oct = '' . $s[$count]; /** @noinspection NotOptimalIfConditionsInspection */ - if ($count + 1 < $n && - \ord($s[$count + 1]) >= 48 && - \ord($s[$count + 1]) <= 57 + if ( + $count + 1 < $n + && \ord($s[$count + 1]) >= 48 + && \ord($s[$count + 1]) <= 57 ) { $count++; $oct .= $s[$count]; /** @noinspection NotOptimalIfConditionsInspection */ - if ($count + 1 < $n && - \ord($s[$count + 1]) >= 48 && - \ord($s[$count + 1]) <= 57 + if ( + $count + 1 < $n + && \ord($s[$count + 1]) >= 48 + && \ord($s[$count + 1]) <= 57 ) { $oct .= $s[++$count]; } diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfToken.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfToken.php index 4abda09baa7..012b9fd26c4 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfToken.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfToken.php @@ -1,9 +1,10 @@ value = $token; return $v; diff --git a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfType.php b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfType.php index 6ce3c8cc364..7672dcdc1be 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfType.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfParser/Type/PdfType.php @@ -1,9 +1,10 @@ parser !== null) { - /** @noinspection PhpInternalEntityUsedInspection */ $this->parser->cleanUp(); } } @@ -165,9 +164,22 @@ class PdfReader $page = $this->parser->getIndirectObject($page->value); $dict = PdfType::resolve($page, $this->parser); $type = PdfDictionary::get($dict, 'Type'); + if ($type->value === 'Pages') { $kids = PdfType::resolve(PdfDictionary::get($dict, 'Kids'), $this->parser); - $page = $this->pages[$pageNumber - 1] = $readPages($kids); + try { + $page = $this->pages[$pageNumber - 1] = $readPages($kids); + } catch (PdfReaderException $e) { + if ($e->getCode() !== PdfReaderException::KIDS_EMPTY) { + throw $e; + } + + // let's reset the pages array and read all page objects + $this->pages = []; + $this->readPages(true); + // @phpstan-ignore-next-line + $page = $this->pages[$pageNumber - 1]; + } } else { $this->pages[$pageNumber - 1] = $page; } @@ -179,24 +191,25 @@ class PdfReader /** * Walk the page tree and resolve all indirect objects of all pages. * - * @throws PdfTypeException + * @param bool $readAll * @throws CrossReferenceException * @throws PdfParserException + * @throws PdfTypeException */ - protected function readPages() + protected function readPages($readAll = false) { if (\count($this->pages) > 0) { return; } - $readPages = function ($kids, $count) use (&$readPages) { + $readPages = function ($kids, $count) use (&$readPages, $readAll) { $kids = PdfArray::ensure($kids); - $isLeaf = $count->value === \count($kids->value); + $isLeaf = ($count->value === \count($kids->value)); foreach ($kids->value as $reference) { $reference = PdfIndirectObjectReference::ensure($reference); - if ($isLeaf) { + if (!$readAll && $isLeaf) { $this->pages[] = $reference; continue; } diff --git a/mod/assign/feedback/editpdf/fpdi/PdfReader/PdfReaderException.php b/mod/assign/feedback/editpdf/fpdi/PdfReader/PdfReaderException.php index c1159ba750e..99f7d125ce5 100644 --- a/mod/assign/feedback/editpdf/fpdi/PdfReader/PdfReaderException.php +++ b/mod/assign/feedback/editpdf/fpdi/PdfReader/PdfReaderException.php @@ -1,9 +1,10 @@ objectsToCopy[$readerId])) !== null) { try { $object = $parser->getIndirectObject($objectNumber); - } catch (CrossReferenceException $e) { if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); @@ -240,27 +247,24 @@ class Fpdi extends \pdf $string = PdfString::unescape($value->value); $string = $this->_encrypt_data($this->currentObjectNumber, $string); $value->value = \TCPDF_STATIC::_escape($string); - } elseif ($value instanceof PdfHexString) { $filter = new AsciiHex(); $string = $filter->decode($value->value); $string = $this->_encrypt_data($this->currentObjectNumber, $string); $value->value = $filter->encode($string, true); - } elseif ($value instanceof PdfStream) { $stream = $value->getStream(); $stream = $this->_encrypt_data($this->currentObjectNumber, $stream); $dictionary = $value->value; $dictionary->value['Length'] = PdfNumeric::create(\strlen($stream)); $value = PdfStream::create($dictionary, $stream); - } elseif ($value instanceof PdfIndirectObject) { /** - * @var $value PdfIndirectObject + * @var PdfIndirectObject $value */ $this->currentObjectNumber = $this->objectMap[$this->currentReaderId][$value->objectNumber]; } $this->fpdiWritePdfType($value); } -} \ No newline at end of file +} diff --git a/mod/assign/feedback/editpdf/fpdi/TcpdfFpdi.php b/mod/assign/feedback/editpdf/fpdi/TcpdfFpdi.php index 6b617a17f17..9e6825bd3c1 100644 --- a/mod/assign/feedback/editpdf/fpdi/TcpdfFpdi.php +++ b/mod/assign/feedback/editpdf/fpdi/TcpdfFpdi.php @@ -1,9 +1,10 @@ _protectedPutimages(); - } - - /** - * Make the method public as in tFPDF. - */ - public function _putxobjectdict() - { - $this->_protectedPutxobjectdict(); - } - - /** - * Set the page format of the current page. - * - * @param array $size An array with two values defining the size. - * @param string $orientation "L" for landscape, "P" for portrait. - * @throws \BadMethodCallException - */ - public function setPageFormat($size, $orientation) - { - if ($this->currentTemplateId !== null) { - throw new \BadMethodCallException('The page format cannot be changed when writing to a template.'); - } - - if (!\in_array($orientation, ['P', 'L'], true)) { - throw new \InvalidArgumentException(\sprintf( - 'Invalid page orientation "%s"! Only "P" and "L" are allowed!', - $orientation - )); - } - - $size = $this->_getpagesize($size); - - if ($orientation != $this->CurOrientation - || $size[0] != $this->CurPageSize[0] - || $size[1] != $this->CurPageSize[1] - ) { - // New size or orientation - if ($orientation === 'P') { - $this->w = $size[0]; - $this->h = $size[1]; - } else { - $this->w = $size[1]; - $this->h = $size[0]; - } - $this->wPt = $this->w * $this->k; - $this->hPt = $this->h * $this->k; - $this->PageBreakTrigger = $this->h - $this->bMargin; - $this->CurOrientation = $orientation; - $this->CurPageSize = $size; - - $this->PageSizes[$this->page] = array($this->wPt, $this->hPt); - } - } - - /** - * @inheritdoc - */ - protected function _put($s, $newLine = true) - { - if ($newLine) { - $this->buffer .= $s . "\n"; - } else { - $this->buffer .= $s; - } - } -} \ No newline at end of file + use FpdfTplTrait; +} diff --git a/mod/assign/feedback/editpdf/fpdi/Tfpdf/Fpdi.php b/mod/assign/feedback/editpdf/fpdi/Tfpdf/Fpdi.php index f22625f08e2..83a1e8753db 100644 --- a/mod/assign/feedback/editpdf/fpdi/Tfpdf/Fpdi.php +++ b/mod/assign/feedback/editpdf/fpdi/Tfpdf/Fpdi.php @@ -1,9 +1,10 @@ objectsToCopy[$readerId])) !== null) { try { $object = $parser->getIndirectObject($objectNumber); - } catch (CrossReferenceException $e) { if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); @@ -133,7 +131,7 @@ class Fpdi extends FpdfTpl /** * @inheritdoc */ - public function _putxobjectdict() + protected function _putxobjectdict() { foreach ($this->importedPages as $key => $pageData) { $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R'); @@ -145,20 +143,12 @@ class Fpdi extends FpdfTpl /** * @inheritdoc */ - public function _newobj($n = null) + protected function _put($s, $newLine = true) { - // Begin a new object - if($n === null) - $n = ++$this->n; - $this->offsets[$n] = $this->_getoffset(); - $this->_put($n.' 0 obj'); + if ($newLine) { + $this->buffer .= $s . "\n"; + } else { + $this->buffer .= $s; + } } - - /** - * @inheritdoc - */ - protected function _getoffset() - { - return strlen($this->buffer); - } -} \ No newline at end of file +} diff --git a/mod/assign/feedback/editpdf/fpdi/autoload.php b/mod/assign/feedback/editpdf/fpdi/autoload.php index fd7d4726746..419e8319f18 100644 --- a/mod/assign/feedback/editpdf/fpdi/autoload.php +++ b/mod/assign/feedback/editpdf/fpdi/autoload.php @@ -1,18 +1,20 @@ fpdi FPDI MIT - 2.2.0 + 2.3.5