--- /dev/null
+<?php
+/**
+ * This exception is thrown when the checksum (sometimes called "hash") of the
+ * package data (aka "message" emcoded with BASE64) is not valid.
+ *
+ * @author Roland Haeder <webmaster@ship-simu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.ship-simu.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+class InvalidDataChecksumException extends FrameworkException {
+ /**
+ * The super constructor for all exceptions
+ *
+ * @param $messageArray Error message array
+ * @param $code Error code
+ * @return void
+ */
+ public function __construct (array $messageArray, $code) {
+ // Construct the message
+ $message = sprintf("[%s:%d] The checksum %s doesn't match the checksum of the content: %s",
+ $messageArray[0]->__toString(),
+ $this->getLine(),
+ $messageArray[0]->getHashFromContentSessionId($messageArray[1], $messageArray[2][NetworkPackage::PACKAGE_DATA_SENDER]),
+ $messageArray[1][NetworkPackage::PACKAGE_CONTENT_CHECKSUM]
+ );
+
+ // Call parent exception constructor
+ parent::__construct($message, $code);
+ }
+}
+
+// [EOF]
+?>
const PACKAGE_MASK_SEPARATOR = '^';
/**
- * SEPARATOR for checksum
+ * Size of an array created by invoking
+ * explode(NetworkPackage::PACKAGE_MASK_SEPARATOR, $content).
+ */
+ const PACKAGE_CONTENT_ARRAY_SIZE = 4;
+
+ /**
+ * Separator for checksum
*/
const PACKAGE_CHECKSUM_SEPARATOR = '_';
const INDEX_PACKAGE_STATUS = 3;
const INDEX_PACKAGE_SIGNATURE = 4;
+ /**
+ * Size of the decoded data array ('status' is not included)
+ */
+ const DECODED_DATA_ARRAY_SIZE = 4;
+
+ /**
+ * Named array elements for decoded package content
+ */
+ const PACKAGE_CONTENT_EXTENSION = 'compressor';
+ const PACKAGE_CONTENT_MESSAGE = 'message';
+ const PACKAGE_CONTENT_TAGS = 'tags';
+ const PACKAGE_CONTENT_CHECKSUM = 'checksum';
+
/**
* Named array elements for package data
*/
*/
const TCP_PACKAGE_SIZE = 512;
- /**
- * Size of the decoded data array
- */
- const DECODED_DATA_ARRAY_SIZE = 4;
-
/**************************************************************************
* Stacker for out-going packages *
**************************************************************************/
}
/**
- * "Getter" for hash from given content and helper instance
+ * "Getter" for hash from given content
*
- * @param $content Raw package content
- * @param $helperInstance An instance of a HelpableHub class
- * @param $nodeInstance An instance of a NodeHelper class
- * @return $hash Hash for given package content
+ * @param $content Raw package content
+ * @return $hash Hash for given package content
*/
private function getHashFromContent ($content) {
// Debug message
return $hash;
}
+ /**
+ * Checks whether the checksum (sometimes called "hash") is the same
+ *
+ * @param $decodedContent Package raw content
+ * @param $decodedData Whole raw package data array
+ * @return $isChecksumValid Whether the checksum is the same
+ */
+ private function isChecksumValid (array $decodedContent, array $decodedData) {
+ // Get checksum
+ $checksum = $this->getHashFromContentSessionId($decodedContent, $decodedData[self::PACKAGE_DATA_SENDER]);
+
+ // Is it the same?
+ $isChecksumValid = ($checksum == $decodedContent[self::PACKAGE_CONTENT_CHECKSUM]);
+
+ // Return it
+ return $isChecksumValid;
+ }
+
/**
* Change the package with given status in given stack
*
// Pop the entry (it should be it)
$nextData = $this->getStackerInstance()->popNamed($stackerName);
- // Compare both arrays
+ // Compare both signatures
assert($nextData[self::PACKAGE_DATA_SIGNATURE] == $packageData[self::PACKAGE_DATA_SIGNATURE]);
// Temporary set the new status
$this->getStackerInstance()->pushNamed($stackerName, $packageData);
}
+ /**
+ * "Getter" for hash from given content and sender's session id
+ *
+ * @param $decodedContent Decoded package content
+ * @param $sessionId Session id of the sender
+ * @return $hash Hash for given package content
+ */
+ public function getHashFromContentSessionId (array $decodedContent, $sessionId) {
+ // Debug message
+ //* NOISY-DEBUG: */ $this->debugOutput('NETWORK-PACKAGE: content[md5]=' . md5($decodedContent[self::PACKAGE_CONTENT_MESSAGE]) . ',sender=' . $sessionId . ',compressor=' . $decodedContent[self::PACKAGE_CONTENT_EXTENSION]);
+
+ // Create the hash
+ // @TODO crc32() is very weak, but it needs to be fast
+ $hash = crc32(
+ $decodedContent[self::PACKAGE_CONTENT_MESSAGE] .
+ self::PACKAGE_CHECKSUM_SEPARATOR .
+ $sessionId .
+ self::PACKAGE_CHECKSUM_SEPARATOR .
+ $decodedContent[self::PACKAGE_CONTENT_EXTENSION]
+ );
+
+ // And return it
+ return $hash;
+ }
+
///////////////////////////////////////////////////////////////////////////
// Delivering packages / raw data
///////////////////////////////////////////////////////////////////////////
return $signature;
}
+ /**
+ * Checks whether the signature of given package data is 'valid', here that
+ * means it is the same or not.
+ *
+ * @param $decodedArray An array with 'decoded' (explode() was mostly called) data
+ * @return $isSignatureValid Whether the signature is valid
+ * @todo Unfinished area, signature are currently not supported
+ */
+ private function isPackageSignatureValid (array $decodedArray) {
+ // Generate the signature of comparing it
+ $signature = $this->generatePackageSignature($decodedArray[self::INDEX_PACKAGE_CONTENT], $decodedArray[self::INDEX_PACKAGE_SENDER]);
+
+ // Is it the same?
+ //$isSignatureValid =
+ die('signature='.$signature.print_r($decodedArray,true));
+ }
+
/**
* "Enqueues" raw content into this delivery class by reading the raw content
* from given template instance and pushing it on the 'undeclared' stack.
// Assert on count (should be always 3)
assert(count($decodedArray) == self::DECODED_DATA_ARRAY_SIZE);
- // Create 'decodedData' array with all assoziative array elements
+ // Generate the signature of comparing it
+ /*
+ * @todo Unsupported feature commented out
+ if (!$this->isPackageSignatureValid($decodedArray)) {
+ // Is not valid, so throw an exception here
+ die('INVALID SIG! UNDER CONSTRUCTION!' . chr(10));
+ } // END - if
+ */
+
+ /*
+ * Create 'decodedData' array with all assoziative array elements,
+ * except signature.
+ */
$decodedData = array(
self::PACKAGE_DATA_SENDER => $decodedArray[self::INDEX_PACKAGE_SENDER],
self::PACKAGE_DATA_RECIPIENT => $decodedArray[self::INDEX_PACKAGE_RECIPIENT],
self::PACKAGE_DATA_CONTENT => $decodedArray[self::INDEX_PACKAGE_CONTENT],
- self::PACKAGE_DATA_STATUS => self::PACKAGE_STATUS_DECODED,
- self::PACKAGE_DATA_SIGNATURE => $this->generatePackageSignature($decodedArray[self::INDEX_PACKAGE_CONTENT], $decodedArray[self::INDEX_PACKAGE_SENDER])
+ self::PACKAGE_DATA_STATUS => self::PACKAGE_STATUS_DECODED
);
// And return it
return $decodedData;
}
+
+ /**
+ * Handles decoded data for this node by "decoding" the 'content' part of
+ * it. Again this method uses explode() for the "decoding" process.
+ *
+ * @param $decodedData An array with decoded raw package data
+ * @return void
+ * @throws InvalidDataChecksumException If the checksum doesn't match
+ */
+ public function handleDecodedData (array $decodedData) {
+ /*
+ * "Decode" the package's content by a simple explode() call, for
+ * details of the array elements, see comments for constant
+ * PACKAGE_MASK.
+ */
+ $decodedContent = explode(self::PACKAGE_MASK_SEPARATOR, $decodedData[self::PACKAGE_DATA_CONTENT]);
+
+ // Assert on array count for a very basic validation
+ assert(count($decodedContent) == self::PACKAGE_CONTENT_ARRAY_SIZE);
+
+ // Convert the indexed array into an associative array
+ $decodedContent = array(
+ // Compressor's extension used to compress the data
+ self::PACKAGE_CONTENT_EXTENSION => $decodedContent[self::INDEX_COMPRESSOR_EXTENSION],
+ // Package data (aka "message") in BASE64-decoded form
+ self::PACKAGE_CONTENT_MESSAGE => base64_decode($decodedContent[self::INDEX_PACKAGE_DATA]),
+ // Tags as an indexed array for "tagging" the message
+ self::PACKAGE_CONTENT_TAGS => explode(self::PACKAGE_TAGS_SEPARATOR, $decodedContent[self::INDEX_TAGS]),
+ // Checksum of the _decoded_ data
+ self::PACKAGE_CONTENT_CHECKSUM => $decodedContent[self::INDEX_CHECKSUM]
+ );
+
+ // Is the checksum valid?
+ if (!$this->isChecksumValid($decodedContent, $decodedData)) {
+ // Is not the same, so throw an exception here
+ throw new InvalidDataChecksumException(array($this, $decodedContent, $decodedData), BaseListener::EXCEPTION_INVALID_DATA_CHECKSUM);
+ } // END - if
+
+ // It is the same, then decompress it, the original message is than fully decoded
+ $decodedContent[self::PACKAGE_CONTENT_MESSAGE] = $this->getCompressorInstance()->decompressStream($decodedContent[self::PACKAGE_CONTENT_MESSAGE]);
+ die('decodedContent='.print_r($decodedContent,true));
+ }
}
// [EOF]