+ /**
+ * "Getter" for databse entry
+ *
+ * @return $entry An array with database entries
+ * @throws NullPointerException If the database result is not found
+ * @throws InvalidDatabaseResultException If the database result is invalid
+ */
+ protected final function getDatabaseEntry () {
+ // Is there an instance?
+ if (is_null($this->getResultInstance())) {
+ // Throw an exception here
+ throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+ } // END - if
+
+ // Rewind it
+ $this->getResultInstance()->rewind();
+
+ // Do we have an entry?
+ if ($this->getResultInstance()->valid() === FALSE) {
+ throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), DatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT);
+ } // END - if
+
+ // Get next entry
+ $this->getResultInstance()->next();
+
+ // Fetch it
+ $entry = $this->getResultInstance()->current();
+
+ // And return it
+ return $entry;
+ }
+
+ /**
+ * Getter for field name
+ *
+ * @param $fieldName Field name which we shall get
+ * @return $fieldValue Field value from the user
+ * @throws NullPointerException If the result instance is null
+ */
+ public final function getField ($fieldName) {
+ // Default field value
+ $fieldValue = NULL;
+
+ // Get result instance
+ $resultInstance = $this->getResultInstance();
+
+ // Is this instance null?
+ if (is_null($resultInstance)) {
+ // Then the user instance is no longer valid (expired cookies?)
+ throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+ } // END - if
+
+ // Get current array
+ $fieldArray = $resultInstance->current();
+ //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($fieldName.':<pre>'.print_r($fieldArray, TRUE).'</pre>');
+
+ // Convert dashes to underscore
+ $fieldName = $this->convertDashesToUnderscores($fieldName);
+
+ // Does the field exist?
+ if (isset($fieldArray[$fieldName])) {
+ // Get it
+ $fieldValue = $fieldArray[$fieldName];
+ } else {
+ // Missing field entry, may require debugging
+ self::createDebugInstance(__CLASS__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']:fieldName=' . $fieldName . ' not found!');
+ }
+
+ // Return it
+ return $fieldValue;
+ }
+
+ /**
+ * Flushs all pending updates to the database layer
+ *
+ * @return void
+ */
+ public function flushPendingUpdates () {
+ // Get result instance
+ $resultInstance = $this->getResultInstance();
+
+ // Do we have data to update?
+ if ((is_object($resultInstance)) && ($resultInstance->ifDataNeedsFlush())) {
+ // Get wrapper class name config entry
+ $configEntry = $resultInstance->getUpdateInstance()->getWrapperConfigEntry();
+
+ // Create object instance
+ $wrapperInstance = ObjectFactory::createObjectByConfiguredName($configEntry);
+
+ // Yes, then send the whole result to the database layer
+ $wrapperInstance->doUpdateByResult($this->getResultInstance());
+ } // END - if
+ }
+
+ /**
+ * Outputs a deprecation warning to the developer.
+ *
+ * @param $message The message we shall output to the developer
+ * @return void
+ * @todo Write a logging mechanism for productive mode
+ */
+ public function deprecationWarning ($message) {
+ // Is developer mode active?
+ if (defined('DEVELOPER')) {
+ // Debug instance is there?
+ if (!is_null($this->getDebugInstance())) {
+ // Output stub message
+ self::createDebugInstance(__CLASS__)->debugOutput($message);
+ } else {
+ // Trigger an error
+ trigger_error($message . "<br />\n");
+ exit;
+ }
+ } else {
+ // @TODO Finish this part!
+ $this->partialStub('Developer mode inactive. Message:' . $message);
+ }
+ }
+
+ /**
+ * Checks whether the given PHP extension is loaded
+ *
+ * @param $phpExtension The PHP extension we shall check
+ * @return $isLoaded Whether the PHP extension is loaded
+ */
+ public final function isPhpExtensionLoaded ($phpExtension) {
+ // Is it loaded?
+ $isLoaded = in_array($phpExtension, get_loaded_extensions());
+
+ // Return result
+ return $isLoaded;
+ }
+
+ /**
+ * "Getter" as a time() replacement but with milliseconds. You should use this
+ * method instead of the encapsulated getimeofday() function.
+ *
+ * @return $milliTime Timestamp with milliseconds
+ */
+ public function getMilliTime () {
+ // Get the time of day as float
+ $milliTime = gettimeofday(TRUE);
+
+ // Return it
+ return $milliTime;
+ }
+
+ /**
+ * Idles (sleeps) for given milliseconds
+ *
+ * @return $hasSlept Whether it goes fine
+ */
+ public function idle ($milliSeconds) {
+ // Sleep is fine by default
+ $hasSlept = TRUE;
+
+ // Idle so long with found function
+ if (function_exists('time_sleep_until')) {
+ // Get current time and add idle time
+ $sleepUntil = $this->getMilliTime() + abs($milliSeconds) / 1000;
+
+ // New PHP 5.1.0 function found, ignore errors
+ $hasSlept = @time_sleep_until($sleepUntil);
+ } else {
+ /*
+ * My Sun station doesn't have that function even with latest PHP
+ * package. :(
+ */
+ usleep($milliSeconds * 1000);
+ }
+
+ // Return result
+ return $hasSlept;
+ }
+ /**
+ * Converts a hexadecimal string, even with negative sign as first string to
+ * a decimal number using BC functions.
+ *
+ * This work is based on comment #86673 on php.net documentation page at:
+ * <http://de.php.net/manual/en/function.dechex.php#86673>
+ *
+ * @param $hex Hexadecimal string
+ * @return $dec Decimal number
+ */
+ protected function hex2dec ($hex) {
+ // Convert to all lower-case
+ $hex = strtolower($hex);
+
+ // Detect sign (negative/positive numbers)
+ $sign = '';
+ if (substr($hex, 0, 1) == '-') {
+ $sign = '-';
+ $hex = substr($hex, 1);
+ } // END - if
+
+ // Decode the hexadecimal string into a decimal number
+ $dec = 0;
+ for ($i = strlen($hex) - 1, $e = 1; $i >= 0; $i--, $e = bcmul($e, 16)) {
+ $factor = self::$hexdec[substr($hex, $i, 1)];
+ $dec = bcadd($dec, bcmul($factor, $e));
+ } // END - for
+
+ // Return the decimal number
+ return $sign . $dec;
+ }
+
+ /**
+ * Converts even very large decimal numbers, also signed, to a hexadecimal
+ * string.
+ *
+ * This work is based on comment #97756 on php.net documentation page at:
+ * <http://de.php.net/manual/en/function.hexdec.php#97756>
+ *
+ * @param $dec Decimal number, even with negative sign
+ * @param $maxLength Optional maximum length of the string
+ * @return $hex Hexadecimal string
+ */
+ protected function dec2hex ($dec, $maxLength = 0) {
+ // maxLength can be zero or devideable by 2
+ assert(($maxLength == 0) || (($maxLength % 2) == 0));
+
+ // Detect sign (negative/positive numbers)
+ $sign = '';
+ if ($dec < 0) {
+ $sign = '-';
+ $dec = abs($dec);
+ } // END - if
+
+ // Encode the decimal number into a hexadecimal string
+ $hex = '';
+ do {
+ $hex = self::$dechex[($dec % (2 ^ 4))] . $hex;
+ $dec /= (2 ^ 4);
+ } while ($dec >= 1);
+
+ /*
+ * Leading zeros are required for hex-decimal "numbers". In some
+ * situations more leading zeros are wanted, so check for both
+ * conditions.
+ */
+ if ($maxLength > 0) {
+ // Prepend more zeros
+ $hex = str_pad($hex, $maxLength, '0', STR_PAD_LEFT);
+ } elseif ((strlen($hex) % 2) != 0) {
+ // Only make string's length dividable by 2
+ $hex = '0' . $hex;
+ }
+
+ // Return the hexadecimal string
+ return $sign . $hex;
+ }
+
+ /**
+ * Converts a ASCII string (0 to 255) into a decimal number.
+ *
+ * @param $asc The ASCII string to be converted
+ * @return $dec Decimal number
+ */
+ protected function asc2dec ($asc) {
+ // Convert it into a hexadecimal number
+ $hex = bin2hex($asc);
+
+ // And back into a decimal number
+ $dec = $this->hex2dec($hex);
+
+ // Return it
+ return $dec;
+ }
+
+ /**
+ * Converts a decimal number into an ASCII string.
+ *
+ * @param $dec Decimal number
+ * @return $asc An ASCII string
+ */
+ protected function dec2asc ($dec) {
+ // First convert the number into a hexadecimal string
+ $hex = $this->dec2hex($dec);
+
+ // Then convert it into the ASCII string
+ $asc = $this->hex2asc($hex);
+
+ // Return it
+ return $asc;
+ }
+
+ /**
+ * Converts a hexadecimal number into an ASCII string. Negative numbers
+ * are not allowed.
+ *
+ * @param $hex Hexadecimal string
+ * @return $asc An ASCII string
+ */
+ protected function hex2asc ($hex) {
+ // Check for length, it must be devideable by 2
+ //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('hex='.$hex);
+ assert((strlen($hex) % 2) == 0);
+
+ // Walk the string
+ $asc = '';
+ for ($idx = 0; $idx < strlen($hex); $idx+=2) {
+ // Get the decimal number of the chunk
+ $part = hexdec(substr($hex, $idx, 2));
+
+ // Add it to the final string
+ $asc .= chr($part);
+ } // END - for
+
+ // Return the final string
+ return $asc;
+ }
+
+ /**
+ * Checks whether the given encoded data was encoded with Base64
+ *
+ * @param $encodedData Encoded data we shall check
+ * @return $isBase64 Whether the encoded data is Base64
+ */
+ protected function isBase64Encoded ($encodedData) {
+ // Determine it
+ $isBase64 = (@base64_decode($encodedData, TRUE) !== FALSE);
+
+ // Return it
+ return $isBase64;
+ }
+
+ /**
+ * "Getter" to get response/request type from analysis of the system.
+ *
+ * @return $responseType Analyzed response type
+ */
+ protected function getResponseTypeFromSystem () {
+ // Default is console
+ $responseType = 'console';
+
+ // Is 'HTTP_HOST' set?
+ if (isset($_SERVER['HTTP_HOST'])) {
+ // Then it is a HTTP response/request
+ $responseType = 'http';
+ } // END - if
+
+ // Return it
+ return $responseType;
+ }
+
+ /**
+ * Gets a cache key from Criteria instance
+ *
+ * @param $criteriaInstance An instance of a Criteria class
+ * @param $onlyKeys Only use these keys for a cache key
+ * @return $cacheKey A cache key suitable for lookup/storage purposes
+ */
+ protected function getCacheKeyByCriteria (Criteria $criteriaInstance, array $onlyKeys = array()) {
+ // Generate it
+ $cacheKey = sprintf('%s@%s',
+ $this->__toString(),
+ $criteriaInstance->getCacheKey($onlyKeys)
+ );
+
+ // And return it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . ': cacheKey=' . $cacheKey);
+ return $cacheKey;
+ }
+
+ /**
+ * Getter for startup time in miliseconds
+ *
+ * @return $startupTime Startup time in miliseconds
+ */
+ protected function getStartupTime () {
+ return self::$startupTime;
+ }
+
+ /**
+ * "Getter" for a printable currently execution time in nice braces
+ *
+ * @return $executionTime Current execution time in nice braces
+ */
+ protected function getPrintableExecutionTime () {
+ // Caculate the execution time
+ $executionTime = microtime(TRUE) - $this->getStartupTime();
+
+ // Pack it in nice braces
+ $executionTime = sprintf('[ %01.5f ] ', $executionTime);
+
+ // And return it
+ return $executionTime;
+ }
+
+ /**
+ * Hashes a given string with a simple but stronger hash function (no salt)
+ * and hex-encode it.
+ *
+ * @param $str The string to be hashed
+ * @return $hash The hash from string $str
+ */
+ public static final function hash ($str) {
+ // Hash given string with (better secure) hasher
+ $hash = bin2hex(mhash(MHASH_SHA256, $str));
+
+ // Return it
+ return $hash;
+ }
+
+ /**
+ * "Getter" for length of hash() output. This will be "cached" to speed up
+ * things.
+ *
+ * @return $length Length of hash() output
+ */
+ public static final function getHashLength () {
+ // Is it cashed?
+ if (is_null(self::$hashLength)) {
+ // No, then hash a string and save its length.
+ self::$hashLength = strlen(self::hash('abc123'));
+ } // END - if
+
+ // Return it
+ return self::$hashLength;
+ }
+
+ /**
+ * Checks whether the given number is really a number (only chars 0-9).
+ *
+ * @param $num A string consisting only chars between 0 and 9
+ * @param $castValue Whether to cast the value to double. Do only use this to secure numbers from Requestable classes.
+ * @param $assertMismatch Whether to assert mismatches
+ * @return $ret The (hopefully) secured numbered value
+ */
+ public function bigintval ($num, $castValue = TRUE, $assertMismatch = FALSE) {
+ // Filter all numbers out
+ $ret = preg_replace('/[^0123456789]/', '', $num);
+
+ // Shall we cast?
+ if ($castValue === TRUE) {
+ // Cast to biggest numeric type
+ $ret = (double) $ret;
+ } // END - if
+
+ // Assert only if requested
+ if ($assertMismatch === TRUE) {
+ // Has the whole value changed?
+ assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
+ } // END - if
+
+ // Return result
+ return $ret;
+ }
+
+ /**
+ * Checks whether the given hexadecimal number is really a hex-number (only chars 0-9,a-f).
+ *
+ * @param $num A string consisting only chars between 0 and 9
+ * @param $assertMismatch Whether to assert mismatches
+ * @return $ret The (hopefully) secured hext-numbered value
+ */
+ public function hexval ($num, $assertMismatch = FALSE) {
+ // Filter all numbers out
+ $ret = preg_replace('/[^0123456789abcdefABCDEF]/', '', $num);
+
+ // Assert only if requested
+ if ($assertMismatch === TRUE) {
+ // Has the whole value changed?
+ assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
+ } // END - if
+
+ // Return result
+ return $ret;
+ }
+
+ /**
+ * Checks whether start/end marker are set
+ *
+ * @param $data Data to be checked
+ * @return $isset Whether start/end marker are set
+ */
+ public final function ifStartEndMarkersSet ($data) {
+ // Determine it
+ $isset = ((substr($data, 0, strlen(BaseRawDataHandler::STREAM_START_MARKER)) == BaseRawDataHandler::STREAM_START_MARKER) && (substr($data, -1 * strlen(BaseRawDataHandler::STREAM_END_MARKER), strlen(BaseRawDataHandler::STREAM_END_MARKER)) == BaseRawDataHandler::STREAM_END_MARKER));
+
+ // ... and return it
+ return $isset;
+ }
+
+ /**
+ * Determines if an element is set in the generic array
+ *
+ * @param $keyGroup Main group for the key
+ * @param $subGroup Sub group for the key
+ * @param $key Key to check
+ * @param $element Element to check
+ * @return $isset Whether the given key is set
+ */
+ protected final function isGenericArrayElementSet ($keyGroup, $subGroup, $key, $element) {
+ // Debug message
+ //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
+
+ // Is it there?
+ $isset = isset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
+
+ // Return it
+ return $isset;
+ }
+ /**
+ * Determines if a key is set in the generic array
+ *
+ * @param $keyGroup Main group for the key
+ * @param $subGroup Sub group for the key
+ * @param $key Key to check
+ * @return $isset Whether the given key is set
+ */
+ protected final function isGenericArrayKeySet ($keyGroup, $subGroup, $key) {
+ // Debug message
+ //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
+
+ // Is it there?
+ $isset = isset($this->genericArray[$keyGroup][$subGroup][$key]);
+
+ // Return it
+ return $isset;
+ }
+
+
+ /**
+ * Determines if a group is set in the generic array
+ *
+ * @param $keyGroup Main group
+ * @param $subGroup Sub group
+ * @return $isset Whether the given group is set
+ */
+ protected final function isGenericArrayGroupSet ($keyGroup, $subGroup) {
+ // Debug message
+ //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
+
+ // Is it there?
+ $isset = isset($this->genericArray[$keyGroup][$subGroup]);
+
+ // Return it
+ return $isset;
+ }
+
+ /**
+ * Getter for sub key group
+ *
+ * @param $keyGroup Main key group
+ * @param $subGroup Sub key group
+ * @return $array An array with all array elements
+ */
+ protected final function getGenericSubArray ($keyGroup, $subGroup) {
+ // Is it there?
+ if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
+ // No, then abort here
+ trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
+ exit;