$handlerInstance = new ChunkHandler();
// Get a FIFO stacker
- $stackerInstance = ObjectFactory::createObjectByConfiguredName('chunk_handler_stacker_class');
+ $stackInstance = ObjectFactory::createObjectByConfiguredName('chunk_handler_stacker_class');
// Init all stacker
- $stackerInstance->initStacks(array(
+ $stackInstance->initStacks(array(
self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP,
self::STACKER_NAME_CHUNKS_WITHOUT_FINAL,
self::STACKER_NAME_ASSEMBLED_RAW_DATA
));
// Set the stacker in this handler
- $handlerInstance->setStackerInstance($stackerInstance);
+ $handlerInstance->setStackInstance($stackInstance);
// Get a crypto instance ...
$cryptoInstance = ObjectFactory::createObjectByConfiguredName('crypto_class');
*/
private function initHandler () {
// Noisy debug line:
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Initializing handler ...');
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Initializing handler ...');
// Init finalPackageChunks
$this->finalPackageChunks = array(
*/
private function isChunkHashValid (array $chunkSplits) {
// Noisy debug line:
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: chunkSplits=' . print_r($chunkSplits, TRUE));
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: chunkSplits=' . print_r($chunkSplits, TRUE));
// Assert on some elements
assert(isset($chunkSplits[self::CHUNK_SPLITS_INDEX_RAW_DATA]));
$isValid = ($chunkSplits[self::CHUNK_SPLITS_INDEX_HASH] === $chunkHash);
// Debug output
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: chunkHash=' . $chunkHash . ',isValid=' . intval($isValid));
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: chunkHash=' . $chunkHash . ',isValid=' . intval($isValid));
// ... and return it
return $isValid;
} // END - if
// Debug message
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber=' . $chunkSplits[self::CHUNK_SPLITS_INDEX_SERIAL] . ',hash=' . $chunkSplits[self::CHUNK_SPLITS_INDEX_HASH]);
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber=' . $chunkSplits[self::CHUNK_SPLITS_INDEX_SERIAL] . ',hash=' . $chunkSplits[self::CHUNK_SPLITS_INDEX_HASH]);
// Add the chunk data (index 2) to the final array and use the serial number as index
$this->finalPackageChunks['content'][$chunkSplits[self::CHUNK_SPLITS_INDEX_SERIAL]] = $chunkSplits[self::CHUNK_SPLITS_INDEX_RAW_DATA];
* @return void
*/
private function verifyChunkSerialNumbers () {
+ // Debug message
+ //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: finalPackageChunks=' . print_r($this->finalPackageChunks, TRUE));
+
+ // Get final hash
+ $finalHash = $this->generateFinalHash(implode('', $this->finalPackageChunks['content']));
+
// Reset the serial number generator
- $this->getFragmenterInstance()->resetSerialNumber();
+ $this->getFragmenterInstance()->resetSerialNumber($finalHash);
// "Walk" through all (content) chunks
foreach ($this->finalPackageChunks['content'] as $serialNumber => $content) {
// Get next serial number
- $nextSerial = $this->getFragmenterInstance()->getNextHexSerialNumber();
+ $nextSerial = $this->getFragmenterInstance()->getNextHexSerialNumber($finalHash);
// Debug output
- /* NOISY-DEBUG */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber=' . $serialNumber . ',nextSerial=' . $nextSerial);
+ //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber=' . $serialNumber . ',nextSerial=' . $nextSerial);
// Is it not the same? Then re-request it
if ($serialNumber != $nextSerial) {
$this->rawPackageData = '';
// That went well, so start assembling all chunks
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Handling ' . count($this->finalPackageChunks['content']) . ' entries ...');
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Handling ' . count($this->finalPackageChunks['content']) . ' entries ...');
foreach ($this->finalPackageChunks['content'] as $serialNumber => $content) {
+ // Assert on 'hash' entry (must always be set)
+ assert(isset($this->finalPackageChunks['hashes'][$serialNumber]));
+
// Debug message
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber=' . $serialNumber . ' - validating ...');
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('finalPackageChunks=' . print_r($this->finalPackageChunks, TRUE) . 'chunkHashes=' . print_r($this->chunkHashes, TRUE));
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber=' . $serialNumber . ',hashes=' . $this->finalPackageChunks['hashes'][$serialNumber] . ' - validating ...');
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('finalPackageChunks=' . print_r($this->finalPackageChunks, TRUE) . 'chunkHashes=' . print_r($this->chunkHashes, TRUE));
// Is this chunk valid? This should be the case
assert($this->isChunkHashValid(array(
assert(in_array($this->finalPackageChunks['hashes'][$serialNumber], $this->chunkHashes));
// Verification okay, add it to the raw data
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Adding ' . strlen($content) . ' bytes as raw package data ...');
$this->rawPackageData .= $content;
} // END - foreach
// Debug output
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: eopChunk[1]=' . $this->eopChunk[1] . ',index=' . (count($this->chunkHashes) - 2) . ',chunkHashes='.print_r($this->chunkHashes, TRUE));
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: eopChunk[1]=' . $this->eopChunk[1] . ',index=' . (count($this->chunkHashes) - 2) . ',chunkHashes='.print_r($this->chunkHashes, TRUE));
// The last chunk hash must match with the one from eopChunk[1]
assert($this->eopChunk[1] == $this->chunkHashes[count($this->chunkHashes) - 2]);
}
+ /**
+ * Generate final hash if EOP chunk is found, else an assert will happen.
+ *
+ * @param $rawPackageData Raw package data
+ * @return $finalHash Final hash if EOP chunk is found
+ */
+ private function generateFinalHash ($rawPackageData) {
+ // Make sure the raw package data is given
+ assert((is_string($rawPackageData)) && (!empty($rawPackageData)));
+
+ // Make sure the EOP chunk is set
+ assert((isset($this->eopChunk[0])) && (isset($this->eopChunk[1])));
+ assert((is_string($this->eopChunk[0])) && (!empty($this->eopChunk[0])));
+
+ // Hash the raw data
+ $finalHash = $this->getCryptoInstance()->hashString($rawPackageData, $this->eopChunk[0], FALSE);
+
+ // Return it
+ return $finalHash;
+ }
+
/**
* Verifies the finally assembled raw package data by comparing it against
* the final hash.
* @return void
*/
private function verifyRawPackageData () {
- // Hash the raw package data for final verification
- $finalHash = $this->getCryptoInstance()->hashString($this->rawPackageData, $this->eopChunk[0], FALSE);
+ // Generate final hash
+ $finalHash = $this->generateFinalHash($this->rawPackageData);
// Is it the same?
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: eopChunk[1]=' . $this->eopChunk[1] . ',finalHash=' . $finalHash);
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: eopChunk[1]=' . $this->eopChunk[1] . ',finalHash=' . $finalHash);
assert($finalHash == $this->eopChunk[0]);
}
}
// Do we have some pending chunks (no final)?
- while (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_CHUNKS_WITHOUT_FINAL)) {
+ while (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_CHUNKS_WITHOUT_FINAL)) {
// Then get it first and add it before the EOP chunks
- array_unshift($chunks, $this->getStackerInstance()->popNamed(self::STACKER_NAME_CHUNKS_WITHOUT_FINAL));
+ array_unshift($chunks, $this->getStackInstance()->popNamed(self::STACKER_NAME_CHUNKS_WITHOUT_FINAL));
} // END - while
// Add all chunks to the FIFO stacker
foreach ($chunks as $chunk) {
// Add the chunk
- $this->getStackerInstance()->pushNamed(self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP, $chunk);
+ $this->getStackInstance()->pushNamed(self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP, $chunk);
} // END - foreach
}
// Add all chunks to the FIFO stacker
foreach ($chunks as $chunk) {
// Add the chunk
- $this->getStackerInstance()->pushNamed(self::STACKER_NAME_CHUNKS_WITHOUT_FINAL, $chunk);
+ $this->getStackInstance()->pushNamed(self::STACKER_NAME_CHUNKS_WITHOUT_FINAL, $chunk);
} // END - foreach
}
*/
public function ifUnhandledChunksWithFinalAvailable () {
// Simply check if the stacker is not empty
- $unhandledChunks = $this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP) === FALSE;
+ $unhandledChunks = $this->getStackInstance()->isStackEmpty(self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP) === FALSE;
// Return result
return $unhandledChunks;
assert($this->ifUnhandledChunksWithFinalAvailable());
// Get an entry from the stacker
- $chunk = $this->getStackerInstance()->popNamed(self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP);
+ $chunk = $this->getStackInstance()->popNamed(self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP);
// Split the string with proper separator character
$chunkSplits = explode(PackageFragmenter::CHUNK_DATA_HASH_SEPARATOR, $chunk);
$this->addChunkToFinalArray($chunkSplits);
// Is the stack now empty?
- if ($this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP)) {
+ if ($this->getStackInstance()->isStackEmpty(self::STACKER_NAME_CHUNKS_WITH_FINAL_EOP)) {
// Then mark the final array as complete
$this->markFinalArrayAsCompleted();
} // END - if
*/
public function ifRawPackageDataIsAvailable () {
// Check it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: this->rawPackageData()=' . strlen($this->rawPackageData) . ',ifUnassembledChunksAvailable()=' . intval($this->ifUnassembledChunksAvailable()));
$isRawPackageDataAvailable = ((!empty($this->rawPackageData)) && (!$this->ifUnassembledChunksAvailable()));
// Return it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: isRawPackageDataAvailable=' . intval($isRawPackageDataAvailable));
return $isRawPackageDataAvailable;
}
assert($this->ifRawPackageDataIsAvailable());
// Then feed it into the next stacker
- $this->getStackerInstance()->pushNamed(self::STACKER_NAME_ASSEMBLED_RAW_DATA, $this->rawPackageData);
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Pushing ' . strlen($this->rawPackageData) . ' bytes to stack ' . self::STACKER_NAME_ASSEMBLED_RAW_DATA . ' ...');
+ $this->getStackInstance()->pushNamed(self::STACKER_NAME_ASSEMBLED_RAW_DATA, $this->rawPackageData);
// ... and reset it
$this->rawPackageData = '';