From 478c8c313a0071bf167e60c3ca2cdc519cbdad47 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Thu, 9 Feb 2023 18:32:21 +0100 Subject: [PATCH] Continued: - added more checks on parameters - added mroe debug lines - converted some old array() to new [] --- .../io_stream/class_FileIoStream.php | 99 +++++++++++++------ .../class_FrameworkRawFileOutputPointer.php | 1 + 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/framework/main/classes/file_directories/io_stream/class_FileIoStream.php b/framework/main/classes/file_directories/io_stream/class_FileIoStream.php index 4255f3e6..a5e8f8b5 100644 --- a/framework/main/classes/file_directories/io_stream/class_FileIoStream.php +++ b/framework/main/classes/file_directories/io_stream/class_FileIoStream.php @@ -12,6 +12,8 @@ use Org\Mxchange\CoreFramework\Stream\Filesystem\FileInputStreamer; use Org\Mxchange\CoreFramework\Stream\Filesystem\FileOutputStreamer; // Import SPL stuff +use \InvalidArgumentException; +use \OutOfBoundsException; use \SplFileInfo; /** @@ -86,24 +88,33 @@ class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, Fil * @param $dataArray The data we shall store to the file * @return void * @see FileOutputStreamer - * @todo This method needs heavy rewrite + * @throws InvalidArgumentException If an invalid parameter was given + * @throws OutOfBoundsException If an expected array element wasn't found */ public final function saveFile (SplFileInfo $fileInfoInstance, array $dataArray) { - // Try it five times - $dirName = ''; - $fileInstance = NULL; + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: fileInfoInstance=%s,dataArray()=%d - CALLED!', $fileInfoInstance, count($dataArray))); + if (count($dataArray) < 2) { + // Not valid array, at least 2 elements must be there! + throw new InvalidArgumentException(sprintf('Parameter "dataArray" should have at least 2 elements, has %d', count($dataArray))); + } else if (!isset($dataArray[0])) { + // Array element 0 not found + throw new OutOfBoundsException(sprintf('Array element dataArray[0] not found, dataArray=%s', json_encode($dataArray))); + } else if (!isset($dataArray[1])) { + // Array element 1 not found + throw new OutOfBoundsException(sprintf('Array element dataArray[1] not found, dataArray=%s', json_encode($dataArray))); + } - for ($idx = 0; $idx < 5; $idx++) { + try { // Get a file output pointer - try { - $fileInstance = ObjectFactory::createObjectByConfiguredName('file_raw_output_class', array($fileInfoInstance, 'wb')); - } catch (FileNotFoundException $e) { - // Bail out - ApplicationEntryPoint::exitApplication('The application has made a fatal error. Exception: ' . $e->__toString() . ' with message: ' . $e->getMessage()); - } + $fileInstance = ObjectFactory::createObjectByConfiguredName('file_raw_output_class', [$fileInfoInstance, 'wb']); + } catch (FileNotFoundException $e) { + // Bail out + ApplicationEntryPoint::exitApplication('The application has made a fatal error. Exception: ' . $e->__toString() . ' with message: ' . $e->getMessage()); } // Write a header information for validation purposes + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: Writing header to fileInstance=%s ...', $fileInstance->__toString())); $fileInstance->writeToFile(sprintf('%s%s%s%s%s%s%s%s%s' . PHP_EOL, self::FILE_IO_FILE_HEADER_ID, self::FILE_IO_SEPARATOR, @@ -117,15 +128,17 @@ class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, Fil )); // Encode the (maybe) binary stream with Base64 + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: Encoding %d bytes to BASE64 string ...', count($dataArray[1]))); $b64Stream = base64_encode($dataArray[1]); - // write the data line by line + // write the data line-by-line $line = str_repeat(' ', 50); $idx = 0; while (strlen($line) == 50) { // Get 50 chars or less $line = substr($b64Stream, $idx, 50); // Save it to the stream + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: Writing %d bytes to file ...', strlen($line))); $fileInstance->writeToFile(sprintf('%s%s%s%s%s' . PHP_EOL, self::FILE_IO_DATA_BLOCK_ID, self::FILE_IO_SEPARATOR, @@ -140,6 +153,9 @@ class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, Fil // Close the file unset($fileInstance); + + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('FILE-IO-STREAM: EXIT!'); } /** @@ -151,6 +167,7 @@ class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, Fil */ public final function loadFileContents (SplFileInfo $infoInstance) { // Initialize some variables and arrays + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: infoInstance=%s - CALLED!', $infoInstance)); $inputBuffer = ''; $lastBuffer = ''; $header = []; @@ -161,12 +178,16 @@ class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, Fil $fileInstance = ObjectFactory::createObjectByConfiguredName('file_raw_input_class', array($infoInstance)); // Read all it's contents (we very and transparently decompress it below) + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: fileInstance=%s', $fileInstance->__toString())); while ($readRawLine = $fileInstance->readFromFile()) { // Add the read line to the buffer + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: Adding %d read bytes to input buffer.', strlen($readRawLine))); $inputBuffer .= $readRawLine; // Break infinite loop maybe caused by the input handler if ($lastBuffer == $inputBuffer) { + // Break out of loop, EOF reached? + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('FILE-IO-STREAM: EOF reached!'); break; } @@ -178,40 +199,52 @@ class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, Fil unset($fileInstance); // Convert it into an array - $inputBuffer = explode(chr(10), $inputBuffer); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: Read inputBuffer=%d bytes from infoInstance=%s', strlen($inputBuffer), $infoInstance)); + $inputArray = explode(chr(10), $inputBuffer); // Now process the read lines and verify it's content - foreach ($inputBuffer as $rawLine) { + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: inputArray()=%d', count($inputArray))); + foreach ($inputArray as $rawLine) { // Trim it a little but not the leading spaces/tab-stops $rawLine = rtrim($rawLine); // Analyze this line + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: rawLine()=%d', strlen($rawLine))); if (substr($rawLine, 0, 5) == self::FILE_IO_FILE_HEADER_ID) { // Header found, so let's extract it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: Found header, rawLine=%s', $rawLine)); $header = explode(self::FILE_IO_SEPARATOR, $rawLine); - $header = trim($header[1]); + $headerLine = trim($header[1]); // Now we must convert it again into an array - $header = explode(self::FILE_IO_CHUNKER, $header); + $header = explode(self::FILE_IO_CHUNKER, $headerLine); // Is the header (maybe) valid? + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: header()=%d', count($header))); if (count($header) != 4) { // Throw an exception throw new InvalidArrayCountException(array($this, 'header', count($header), 4), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT); } } elseif (substr($rawLine, 0, 5) == self::FILE_IO_DATA_BLOCK_ID) { // Is a data line! + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: Data line found rawLine=%s', $rawLine)); $data = explode(self::FILE_IO_SEPARATOR, $rawLine); - $data = $data[1]; + $dataLine = $data[1]; // First element is the data, second the MD5 checksum - $data = explode(self::FILE_IO_CHUNKER, $data); + $data = explode(self::FILE_IO_CHUNKER, $dataLine); // Validate the read line + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: data()=%d', count($data))); if (count($data) == 2) { - if (md5($data[0]) != $data[1]) { + // Generate checksum (MD5 is okay here) + $checksum = md5($data[0]); + + // Check if it matches provided one + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: checksum=%s,data[1]=%s', $checksum, $data[1])); + if ($checksum != $data[1]) { // MD5 hash did not match! - throw new InvalidMD5ChecksumException(array($this, md5($data[0]), $data[1]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH); + throw new InvalidMD5ChecksumException(array($this, $checksum, $data[1]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH); } } else { // Invalid count! @@ -219,16 +252,20 @@ class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, Fil } // Add this to the readData string + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: Adding %d raw data to input stream', strlen($data[0]))); $readData .= $data[0]; } else { // Other raw lines than header/data tagged lines and re-add the new-line char + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: Adding rawLine=%s(%d) + PHP_EOL to input stream', $rawLine, strlen($rawLine))); $readData .= $rawLine . PHP_EOL; } } // Was raw lines read and no header/data? + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: readData()=%d,header()=%d,data()=%d', strlen($readData), count($header), count($data))); if ((!empty($readData)) && (count($header) == 0) && (count($data) == 0)) { // Return raw lines back + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: readData()=%d - EXIT!', strlen($readData))); return $readData; } @@ -239,25 +276,31 @@ class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, Fil } // Decode all from Base64 - $readData = @base64_decode($readData); + $decodedData = @base64_decode($readData); // Does the size match? - if (strlen($readData) != $header[2]) { + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: decodedData()=%d,header[2]=%d', strlen($decodedData), $header[2])); + if (strlen($decodedData) != $header[2]) { // Size did not match - throw new InvalidDataLengthException(array($this, strlen($readData), $header[2]), self::EXCEPTION_UNEXPECTED_STRING_SIZE); + throw new InvalidDataLengthException(array($this, strlen($decodedData), $header[2]), self::EXCEPTION_UNEXPECTED_STRING_SIZE); } + // Generate checksum from whole read data + $checksum = md5($decodedData); + // Validate the decoded data with the final MD5 hash - if (md5($readData) != $header[3]) { + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: checksum=%s,header[3]=%s', $checksum, $header[3])); + if ($checksum != $header[3]) { // MD5 hash did not match! - throw new InvalidMD5ChecksumException(array($this, md5($readData), $header[3]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH); + throw new InvalidMD5ChecksumException(array($this, $checksum, $header[3]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH); } // Return all in an array - return array( + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-IO-STREAM: header()=%d,decodedData()=%d - EXIT!', count($header), strlen($decodedData))); + return [ 'header' => $header, - 'data' => $readData - ); + 'data' => $decodedData, + ]; } /** diff --git a/framework/main/classes/file_directories/output/raw/class_FrameworkRawFileOutputPointer.php b/framework/main/classes/file_directories/output/raw/class_FrameworkRawFileOutputPointer.php index abdc30bc..fa724376 100644 --- a/framework/main/classes/file_directories/output/raw/class_FrameworkRawFileOutputPointer.php +++ b/framework/main/classes/file_directories/output/raw/class_FrameworkRawFileOutputPointer.php @@ -65,6 +65,7 @@ class FrameworkRawFileOutputPointer extends BaseFileIo implements OutputPointer } // Try to open a handler + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('RAW-FILE-OUTPUT-POINTER: Invoking fileInstance->openFile(%s) ...', $mode)); $fileObject = $fileInstance->openFile($mode); // Is it valid? -- 2.39.5