]> git.mxchange.org Git - mailer.git/blobdiff - inc/functions.php
Support for chunked HTTP messages added, some code encapsulated:
[mailer.git] / inc / functions.php
index aa59a596b26b71640170e537a8431c9f67ba4d85..79e5d8d5a7541f79bae4a3cc289f8032a9a5e27d 100644 (file)
@@ -16,7 +16,7 @@
  * $Author::                                                          $ *
  * -------------------------------------------------------------------- *
  * Copyright (c) 2003 - 2009 by Roland Haeder                           *
- * Copyright (c) 2009, 2010 by Mailer Developer Team                    *
+ * Copyright (c) 2009 - 2011 by Mailer Developer Team                   *
  * For more information visit: http://www.mxchange.org                  *
  *                                                                      *
  * This program is free software; you can redistribute it and/or modify *
@@ -118,12 +118,12 @@ function sendEmail ($toEmail, $subject, $message, $isHtml = 'N', $mailHeader = '
                                $toEmail = getUserData('email');
                        } else {
                                // Set webmaster
-                               $toEmail = getConfig('WEBMASTER');
+                               $toEmail = getWebmaster();
                        }
                }
        } elseif ($toEmail == '0') {
                // Is the webmaster!
-               $toEmail = getConfig('WEBMASTER');
+               $toEmail = getWebmaster();
        }
        //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, "TO={$toEmail}<br />");
 
@@ -169,8 +169,8 @@ Message : ' . htmlentities(utf8_decode($message)) . '
                // Send Mail away
                return sendRawEmail($toEmail, $subject, $message, $mailHeader);
        } elseif ($isHtml != 'Y') {
-               // Problem found!
-               return sendRawEmail(getConfig('WEBMASTER'), '[PROBLEM:]' . $subject, $message, $mailHeader);
+               // Problem detected while sending a mail, forward it to admin
+               return sendRawEmail(getWebmaster(), '[PROBLEM:]' . $subject, $message, $mailHeader);
        }
 
        // Why did we end up here? This should not happen
@@ -219,7 +219,7 @@ function sendRawEmail ($toEmail, $subject, $message, $headers) {
                $mail->Username   = getConfig('SMTP_USER');
                $mail->Password   = getConfig('SMTP_PASSWORD');
                if (empty($headers)) {
-                       $mail->From = getConfig('WEBMASTER');
+                       $mail->From = getWebmaster();
                } else {
                        $mail->From = $headers;
                }
@@ -235,10 +235,10 @@ function sendRawEmail ($toEmail, $subject, $message, $headers) {
                }
 
                $mail->AddAddress($toEmail, '');
-               $mail->AddReplyTo(getConfig('WEBMASTER'), getMainTitle());
-               $mail->AddCustomHeader('Errors-To:' . getConfig('WEBMASTER'));
-               $mail->AddCustomHeader('X-Loop:' . getConfig('WEBMASTER'));
-               $mail->AddCustomHeader('Bounces-To:' . getConfig('WEBMASTER'));
+               $mail->AddReplyTo(getWebmaster(), getMainTitle());
+               $mail->AddCustomHeader('Errors-To:' . getWebmaster());
+               $mail->AddCustomHeader('X-Loop:' . getWebmaster());
+               $mail->AddCustomHeader('Bounces-To:' . getWebmaster());
                $mail->Send();
 
                // Has an error occured?
@@ -427,6 +427,9 @@ function translateGender ($gender) {
 
 // "Translates" the user status
 function translateUserStatus ($status) {
+       // Default status is unknown if something goes through
+       $ret = '{--ACCOUNT_STATUS_UNKNOWN--}';
+
        // Generate message depending on status
        switch ($status) {
                case 'UNCONFIRMED':
@@ -653,10 +656,10 @@ function array_pk_sort (&$array, $a_sort, $primary_key = '0', $order = -1, $nums
 //
 function generateRandomCode ($length, $code, $userid, $DATA = '') {
        // Build server string
-       $server = $_SERVER['PHP_SELF'] . getEncryptSeperator() . detectUserAgent() . getEncryptSeperator() . getenv('SERVER_SOFTWARE') . getEncryptSeperator() . detectRemoteAddr();
+       $server = $_SERVER['PHP_SELF'] . getEncryptSeperator() . detectUserAgent() . getEncryptSeperator() . getenv('SERVER_SOFTWARE') . getEncryptSeperator() . detectRealIpAddress() . getEncryptSeperator() . detectRemoteAddr();
 
        // Build key string
-       $keys = getConfig('SITE_KEY') . getEncryptSeperator() . getConfig('DATE_KEY');
+       $keys = getSiteKey() . getEncryptSeperator() . getDateKey();
        if (isConfigEntrySet('secret_key')) {
                $keys .= getEncryptSeperator().getSecretKey();
        } // END - if
@@ -687,22 +690,26 @@ function generateRandomCode ($length, $code, $userid, $DATA = '') {
 
        if (isConfigEntrySet('master_salt')) {
                // Generate hash with master salt from modula of number with the prime number and other data
-               $saltedHash = generateHash(($a % getPrime()) . getEncryptSeperator() . $server . getEncryptSeperator() . $keys . getEncryptSeperator() . $data . getEncryptSeperator() . getConfig('DATE_KEY') . getEncryptSeperator() . $a, getMasterSalt());
+               $saltedHash = generateHash(($a % getPrime()) . getEncryptSeperator() . $server . getEncryptSeperator() . $keys . getEncryptSeperator() . $data . getEncryptSeperator() . getDateKey() . getEncryptSeperator() . $a, getMasterSalt());
 
                // Create number from hash
-               $rcode = hexdec(substr($saltedHash, strlen(getMasterSalt()), 9)) / abs(getConfig('rand_no') - $a + sqrt(getConfig('_ADD'))) / pi();
+               $rcode = hexdec(substr($saltedHash, strlen(getMasterSalt()), 9)) / abs(getRandNo() - $a + sqrt(getConfig('_ADD'))) / pi();
        } else {
                // Generate hash with "hash of site key" from modula of number with the prime number and other data
-               $saltedHash = generateHash(($a % getPrime()) . getEncryptSeperator() . $server . getEncryptSeperator() . $keys . getEncryptSeperator() . $data . getEncryptSeperator() . getConfig('DATE_KEY') . getEncryptSeperator() . $a, substr(sha1(getConfig('SITE_KEY')), 0, getSaltLength()));
+               $saltedHash = generateHash(($a % getPrime()) . getEncryptSeperator() . $server . getEncryptSeperator() . $keys . getEncryptSeperator() . $data . getEncryptSeperator() . getDateKey() . getEncryptSeperator() . $a, substr(sha1(getSiteKey()), 0, getSaltLength()));
 
                // Create number from hash
-               $rcode = hexdec(substr($saltedHash, 8, 9)) / abs(getConfig('rand_no') - $a + sqrt(getConfig('_ADD'))) / pi();
+               $rcode = hexdec(substr($saltedHash, 8, 9)) / abs(getRandNo() - $a + sqrt(getConfig('_ADD'))) / pi();
        }
 
        // At least 10 numbers shall be secure enought!
        $len = getCodeLength();
-       if ($len == '0') $len = $length;
-       if ($len == '0') $len = 10;
+       if ($len == '0') {
+               $len = $length;
+       } // END - if
+       if ($len == '0') {
+               $len = 10;
+       } // END - if
 
        // Cut off requested counts of number
        $return = substr(str_replace('.', '', $rcode), 0, $len);
@@ -812,7 +819,9 @@ function extractHostnameFromUrl (&$script) {
 
        // Extract host name
        $host = str_replace('http://', '', $url);
-       if (isInString('/', $host)) $host = substr($host, 0, strpos($host, '/'));
+       if (isInString('/', $host)) {
+               $host = substr($host, 0, strpos($host, '/'));
+       } // END - if
 
        // Generate relative URL
        //* DEBUG: */ debugOutput('SCRIPT=' . $script);
@@ -825,22 +834,24 @@ function extractHostnameFromUrl (&$script) {
        }
 
        //* DEBUG: */ debugOutput('SCRIPT=' . $script);
-       if (substr($script, 0, 1) == '/') $script = substr($script, 1);
+       if (substr($script, 0, 1) == '/') {
+               $script = substr($script, 1);
+       } // END - if
 
        // Return host name
        return $host;
 }
 
 // Send a GET request
-function sendGetRequest ($script, $data = array()) {
-       // Extract host name from script
+function sendGetRequest ($script, $data = array(), $removeHeader = false) {
+       // Extract hostname and port from script
        $host = extractHostnameFromUrl($script);
 
        // Add data
        $body = http_build_query($data, '', '&');
 
        // There should be data, else we don't need to extend $script with $body
-       if (empty($body)) {
+       if (!empty($body)) {
                // Do we have a question-mark in the script?
                if (strpos($script, '?') === false) {
                        // No, so first char must be question mark
@@ -854,7 +865,9 @@ function sendGetRequest ($script, $data = array()) {
                $script .= $body;
 
                // Remove trailed & to make it more conform
-               if (substr($script, -1, 1) == '&') $script = substr($script, 0, -1);
+               if (substr($script, -1, 1) == '&') {
+                       $script = substr($script, 0, -1);
+               } // END - if
        } // END - if
 
        // Generate GET request header
@@ -875,19 +888,18 @@ function sendGetRequest ($script, $data = array()) {
        // Send the raw request
        $response = sendRawRequest($host, $request);
 
+       // Should we remove header lines?
+       if ($removeHeader === true) {
+               // Okay, remove them
+               $response = removeHttpHeaderFromResponse($response);
+       } // END - if
+
        // Return the result to the caller function
        return $response;
 }
 
 // Send a POST request
-function sendPostRequest ($script, $postData) {
-       // Is postData an array?
-       if (!is_array($postData)) {
-               // Abort here
-               logDebugMessage(__FUNCTION__, __LINE__, sprintf("postData is not an array. Type: %s", gettype($postData)));
-               return array('', '', '');
-       } // END - if
-
+function sendPostRequest ($script, array $postData, $removeHeader = false) {
        // Extract host name from script
        $host = extractHostnameFromUrl($script);
 
@@ -913,6 +925,12 @@ function sendPostRequest ($script, $postData) {
        // Send the raw request
        $response = sendRawRequest($host, $request);
 
+       // Should we remove header lines?
+       if ($removeHeader === true) {
+               // Okay, remove them
+               $response = removeHttpHeaderFromResponse($response);
+       } // END - if
+
        // Return the result to the caller function
        return $response;
 }
@@ -920,7 +938,11 @@ function sendPostRequest ($script, $postData) {
 // Sends a raw request to another host
 function sendRawRequest ($host, $request) {
        // Init errno and errdesc with 'all fine' values
-       $errno = '0'; $errdesc = '';
+       $errno = '0';
+       $errdesc = '';
+
+       // Default port is 80
+       $port = 80;
 
        // Initialize array
        $response = array('', '', '');
@@ -937,6 +959,17 @@ function sendRawRequest ($host, $request) {
        // Load include
        loadIncludeOnce('inc/classes/resolver.class.php');
 
+       // Extract port part from host
+       $portArray = explode(':', $host);
+       if (count($portArray) == 2) {
+               // Extract host and port
+               $host = $portArray[0];
+               $port = $portArray[1];
+       } elseif (count($portArray) > 2) {
+               // This should not happen!
+               debug_report_bug(__FUNCTION__, __LINE__, 'Invalid ' . $host . '. Please report this to the Mailer-Project team.');
+       }
+
        // Get resolver instance
        $resolver = new HostnameResolver();
 
@@ -944,16 +977,16 @@ function sendRawRequest ($host, $request) {
        //* DEBUG: */ die('SCRIPT=' . $script);
        if ($useProxy === true) {
                // Resolve hostname into IP address
-               $ip = $resolver->resolveHostname(compileRawCode(getConfig('proxy_host')));
+               $ip = $resolver->resolveHostname(compileRawCode(getProxyHost()));
 
                // Connect to host through proxy connection
-               $fp = fsockopen($ip, bigintval(getConfig('proxy_port')), $errno, $errdesc, 30);
+               $fp = fsockopen($ip, bigintval(getProxyPort()), $errno, $errdesc, 30);
        } else {
                // Resolve hostname into IP address
                $ip = $resolver->resolveHostname($host);
 
                // Connect to host directly
-               $fp = fsockopen($ip, 80, $errno, $errdesc, 30);
+               $fp = fsockopen($ip, $port, $errno, $errdesc, 30);
        }
 
        // Is there a link?
@@ -970,7 +1003,7 @@ function sendRawRequest ($host, $request) {
        // Do we use proxy?
        if ($useProxy === true) {
                // Setup proxy tunnel
-               $response = setupProxyTunnel($host, $fp);
+               $response = setupProxyTunnel($host, $port, $fp);
 
                // If the response is invalid, abort
                if ((count($response) == 3) && (empty($response[0])) && (empty($response[1])) && (empty($response[2]))) {
@@ -1013,7 +1046,7 @@ function sendRawRequest ($host, $request) {
                } // END - if
 
                // Add it to response
-               $response[] = trim($line);
+               $response[] = $line;
        } // END - while
 
        // Close socket
@@ -1060,6 +1093,9 @@ function sendRawRequest ($host, $request) {
                // Not found / access forbidden
                logDebugMessage(__FUNCTION__, __LINE__, 'Unexpected status code ' . $response[0] . ' detected. "200 OK" was expected.');
                $response = array('', '', '');
+       } else {
+               // Check array for chuncked encoding
+               $response = unchunkHttpResponse($response);
        } // END - if
 
        // Return response
@@ -1067,18 +1103,18 @@ function sendRawRequest ($host, $request) {
 }
 
 // Sets up a proxy tunnel for given hostname and through resource
-function setupProxyTunnel ($host, $resource) {
+function setupProxyTunnel ($host, $port, $resource) {
        // Initialize array
        $response = array('', '', '');
 
        // Generate CONNECT request header
-       $proxyTunnel  = 'CONNECT ' . $host . ':80 HTTP/1.0' . getConfig('HTTP_EOL');
+       $proxyTunnel  = 'CONNECT ' . $host . ':' . $port . ' HTTP/1.0' . getConfig('HTTP_EOL');
        $proxyTunnel .= 'Host: ' . $host . getConfig('HTTP_EOL');
 
        // Use login data to proxy? (username at least!)
-       if (getConfig('proxy_username') != '') {
+       if (getProxyUsername() != '') {
                // Add it as well
-               $encodedAuth = base64_encode(compileRawCode(getConfig('proxy_username')) . ':' . compileRawCode(getConfig('proxy_password')));
+               $encodedAuth = base64_encode(compileRawCode(getProxyUsername()) . ':' . compileRawCode(getProxyPassword()));
                $proxyTunnel .= 'Proxy-Authorization: Basic ' . $encodedAuth . getConfig('HTTP_EOL');
        } // END - if
 
@@ -1107,6 +1143,76 @@ function setupProxyTunnel ($host, $resource) {
        return $respArray;
 }
 
+// Check array for chuncked encoding
+function unchunkHttpResponse (array $response) {
+       // Default is not chunked
+       $isChunked = false;
+
+       // Check if we have chunks
+       foreach ($response as $line) {
+               // Make lower-case and trim it
+               $line = trim(strtolower($line));
+
+               // Entry found?
+               if ((strpos($line, 'transfer-encoding') !== false) && (strpos($line, 'chunked') !== false)) {
+                       // Found!
+                       $isChunked = true;
+                       break;
+               } // END - if
+       } // END - foreach
+
+       // Is it chunked?
+       if ($isChunked === true) {
+               // Good, we still have the HTTP headers in there, so we need to get rid
+               // of them temporarly
+               //* DEBUG: */ die('<pre>'.htmlentities(print_r(removeHttpHeaderFromResponse($response), true)).'</pre>');
+               $tempResponse = http_chunked_decode(implode('', removeHttpHeaderFromResponse($response)));
+
+               // We got a string back from http_chunked_decode(), so we need to convert it back to an array
+               //* DEBUG: */ die('tempResponse['.strlen($tempResponse).']=<pre>'.replaceReturnNewLine(htmlentities($tempResponse)).'</pre>');
+
+               // Re-add the headers
+               $response = merge_array($GLOBALS['http_headers'], stringToArray("\n", $tempResponse));
+       } // END - if
+
+       // Return the unchunked array
+       return $response;
+}
+
+// Removes HTTP header lines from a response array (e.g. output from send<Get|Post>Request() )
+function removeHttpHeaderFromResponse (array $response) {
+       // Save headers for later usage
+       $GLOBALS['http_headers'] = array();
+
+       // The first array element has to contain HTTP
+       if ((isset($response[0])) && (substr(strtoupper($response[0]), 0, 5) == 'HTTP/')) {
+               // Okay, we have headers, now remove them with a second array
+               $response2 = $response;
+               foreach ($response as $line) {
+                       // Remove line
+                       array_shift($response2);
+
+                       // Add full line to temporary global array
+                       $GLOBALS['http_headers'][] = $line;
+
+                       // Trim it for testing
+                       $lineTest = trim($line);
+
+                       // Is this line empty?
+                       if (empty($lineTest)) {
+                               // Then stop here
+                               break;
+                       } // END - if
+               } // END - foreach
+
+               // Write back the array
+               $response = $response2;
+       } // END - if
+
+       // Return the modified response array
+       return $response;
+}
+
 // Taken from www.php.net isInStringIgnoreCase() user comments
 function isEmailValid ($email) {
        // Check first part of email address
@@ -1170,10 +1276,10 @@ function generateHash ($plainText, $salt = '', $hash = true) {
        // When the salt is empty build a new one, else use the first x configured characters as the salt
        if (empty($salt)) {
                // Build server string for more entropy
-               $server = $_SERVER['PHP_SELF'] . getEncryptSeperator() . detectUserAgent() . getEncryptSeperator() . getenv('SERVER_SOFTWARE') . getEncryptSeperator() . detectRemoteAddr();
+               $server = $_SERVER['PHP_SELF'] . getEncryptSeperator() . detectUserAgent() . getEncryptSeperator() . getenv('SERVER_SOFTWARE') . getEncryptSeperator() . detectRealIpAddress() . getEncryptSeperator() . detectRemoteAddr();
 
                // Build key string
-               $keys   = getConfig('SITE_KEY') . getEncryptSeperator() . getConfig('DATE_KEY') . getEncryptSeperator() . getSecretKey() . getEncryptSeperator() . getFileHash() . getEncryptSeperator() . getDateFromPatchTime() . getEncryptSeperator() . getMasterSalt();
+               $keys   = getSiteKey() . getEncryptSeperator() . getDateKey() . getEncryptSeperator() . getSecretKey() . getEncryptSeperator() . getFileHash() . getEncryptSeperator() . getDateFromPatchTime() . getEncryptSeperator() . getMasterSalt();
 
                // Additional data
                $data = $plainText . getEncryptSeperator() . uniqid(mt_rand(), true) . getEncryptSeperator() . time();
@@ -1182,7 +1288,7 @@ function generateHash ($plainText, $salt = '', $hash = true) {
                $a = time() + getConfig('_ADD') - 1;
 
                // Generate SHA1 sum from modula of number and the prime number
-               $sha1 = sha1(($a % getPrime()) . $server . getEncryptSeperator() . $keys . getEncryptSeperator() . $data . getEncryptSeperator() . getConfig('DATE_KEY') . getEncryptSeperator() . $a);
+               $sha1 = sha1(($a % getPrime()) . $server . getEncryptSeperator() . $keys . getEncryptSeperator() . $data . getEncryptSeperator() . getDateKey() . getEncryptSeperator() . $a);
                //* DEBUG: */ debugOutput('SHA1=' . $sha1.' ('.strlen($sha1).')<br />');
                $sha1 = scrambleString($sha1);
                //* DEBUG: */ debugOutput('Scrambled=' . $sha1.' ('.strlen($sha1).')<br />');
@@ -1516,13 +1622,13 @@ function getMessageFromErrorCode ($code) {
                        $content['timestamp'] = generateDateTime($content['timestamp'], 1);
 
                        // Calculate hours...
-                       $content['hours'] = round(getConfig('url_tlock') / 60 / 60);
+                       $content['hours'] = round(getUrlTlock() / 60 / 60);
 
                        // Minutes...
-                       $content['minutes'] = round((getConfig('url_tlock') - $content['hours'] * 60 * 60) / 60);
+                       $content['minutes'] = round((getUrlTlock() - $content['hours'] * 60 * 60) / 60);
 
                        // And seconds
-                       $content['seconds'] = round(getConfig('url_tlock') - $content['hours'] * 60 * 60 - $content['minutes'] * 60);
+                       $content['seconds'] = round(getUrlTlock() - $content['hours'] * 60 * 60 - $content['minutes'] * 60);
 
                        // Finally contruct the message
                        $message = loadTemplate('tlock_message', true, $content);
@@ -1685,13 +1791,16 @@ function changeDataInFile ($FQFN, $comment, $prefix, $suffix, $DATA, $seek=0) {
        // An error was detected!
        return false;
 }
+
 // Send notification to admin
-function sendAdminNotification ($subject, $templateName, $content=array(), $userid = '0') {
+function sendAdminNotification ($subject, $templateName, $content = array(), $userid = '0') {
        if ((isExtensionInstalledAndNewer('admins', '0.4.1')) && (function_exists('sendAdminsEmails'))) {
                // Send new way
+               /* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'admins=Y,subject=' . $subject . ',templateName=' . $templateName);
                sendAdminsEmails($subject, $templateName, $content, $userid);
        } else {
-               // Send out out-dated way
+               // Send out-dated way
+               /* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'admins=N,subject=' . $subject . ',templateName=' . $templateName);
                $message = loadEmailTemplate($templateName, $content, $userid);
                sendAdminEmails($subject, $message);
        }
@@ -1844,7 +1953,7 @@ function rebuildCache ($cache, $inc = '', $force = false) {
                // Include file given?
                if (!empty($inc)) {
                        // Construct FQFN
-                       $inc = sprintf("inc/loader/load_cache-%s.php", $inc);
+                       $inc = sprintf("inc/loader/load-%s.php", $inc);
 
                        // Is the include there?
                        if (isIncludeReadable($inc)) {
@@ -1852,7 +1961,7 @@ function rebuildCache ($cache, $inc = '', $force = false) {
                                //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, "inc={$inc} - LOADED!<br />");
                                loadInclude($inc);
                        } else {
-                               // Include not found!
+                               // Include not found
                                logDebugMessage(__FUNCTION__, __LINE__, 'Include ' . $inc . ' not found. cache=' . $cache);
                        }
                } // END - if
@@ -1860,12 +1969,12 @@ function rebuildCache ($cache, $inc = '', $force = false) {
 }
 
 // Determines the real remote address
-function determineRealRemoteAddress () {
+function determineRealRemoteAddress ($remoteAddr = false) {
        // Is a proxy in use?
-       if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+       if ((isset($_SERVER['HTTP_X_FORWARDED_FOR'])) && (!$remoteAddr)) {
                // Proxy was used
                $address = $_SERVER['HTTP_X_FORWARDED_FOR'];
-       } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
+       } elseif ((isset($_SERVER['HTTP_CLIENT_IP'])) && (!$remoteAddr)) {
                // Yet, another proxy
                $address = $_SERVER['HTTP_CLIENT_IP'];
        } else {
@@ -1885,9 +1994,11 @@ function determineRealRemoteAddress () {
 
 // Adds a bonus mail to the queue
 // This is a high-level function!
-function addNewBonusMail ($data, $mode = '', $output=true) {
+function addNewBonusMail ($data, $mode = '', $output = true) {
        // Use mode from data if not set and availble ;-)
-       if ((empty($mode)) && (isset($data['mode']))) $mode = $data['mode'];
+       if ((empty($mode)) && (isset($data['mode']))) {
+               $mode = $data['mode'];
+       } // END - if
 
        // Generate receiver list
        $receiver = generateReceiverList($data['cat'], $data['receiver'], $mode);
@@ -1909,11 +2020,11 @@ function addNewBonusMail ($data, $mode = '', $output=true) {
 
                // Mail inserted into bonus pool
                if ($output === true) {
-                       loadTemplate('admin_settings_saved', false, '{--ADMIN_BONUS_SEND--}');
+                       displayMessage('{--ADMIN_BONUS_SEND--}');
                } // END - if
        } elseif ($output === true) {
                // More entered than can be reached!
-               loadTemplate('admin_settings_saved', false, '{--ADMIN_MORE_SELECTED--}');
+               displayMessage('{--ADMIN_MORE_SELECTED--}');
        } else {
                // Debug log
                logDebugMessage(__FUNCTION__, __LINE__, 'cat=' . $data['cat'] . ',receiver=' . $data['receiver'] . ',data=' . base64_encode(serialize($data)) . ' More selected, than available!');
@@ -1923,7 +2034,9 @@ function addNewBonusMail ($data, $mode = '', $output=true) {
 // Determines referal id and sets it
 function determineReferalId () {
        // Skip this in non-html-mode and outside ref.php
-       if ((!isHtmlOutputMode()) && (basename($_SERVER['PHP_SELF']) != 'ref.php')) return false;
+       if ((!isHtmlOutputMode()) && (basename($_SERVER['PHP_SELF']) != 'ref.php')) {
+               return false;
+       } // END - if
 
        // Check if refid is set
        if ((isset($GLOBALS['refid'])) && ($GLOBALS['refid'] > 0)) {
@@ -1991,6 +2104,15 @@ function doReset () {
        runFilterChain('reset');
 }
 
+// Enables the reset mode (hourly, weekly and monthly) and runs it
+function doHourly () {
+       // Enable the hourly reset mode
+       $GLOBALS['hourly_enabled'] = true;
+
+       // Run filters (one always!)
+       runFilterChain('hourly');
+}
+
 // Our shutdown-function
 function shutdown () {
        // Call the filter chain 'shutdown'
@@ -2118,7 +2240,7 @@ function getArrayFromDirectory ($baseDir, $prefix, $fileIncludeDirs = false, $ad
 
                        // And skip further processing
                        continue;
-               } elseif (substr($baseFile, 0, strlen($prefix)) != $prefix) {
+               } elseif (!isFilePrefixFound($baseFile, $prefix)) {
                        // Skip this file
                        //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Invalid prefix in file ' . $baseFile . ', prefix=' . $prefix);
                        continue;
@@ -2132,9 +2254,12 @@ function getArrayFromDirectory ($baseDir, $prefix, $fileIncludeDirs = false, $ad
                        continue;
                }
 
+               // Get file' extension (last 4 chars)
+               $fileExtension = substr($baseFile, -4, 4);
+
                // Is the file a PHP script or other?
                //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'baseDir=' . $baseDir . ',prefix=' . $prefix . ',baseFile=' . $baseFile);
-               if ((substr($baseFile, -4, 4) == '.php') || (($fileIncludeDirs === true) && (isDirectory($FQFN)))) {
+               if (($fileExtension == '.php') || (($fileIncludeDirs === true) && (isDirectory($FQFN)))) {
                        // Is this a valid include file?
                        if ($extension == '.php') {
                                // Remove both for extension name
@@ -2150,9 +2275,9 @@ function getArrayFromDirectory ($baseDir, $prefix, $fileIncludeDirs = false, $ad
                                }
                        } else {
                                // We found .php file but should not search for them, why?
-                               debug_report_bug(__FUNCTION__, __LINE__, 'We should find files with extension=' . $extension . ', but we found a PHP script.');
+                               debug_report_bug(__FUNCTION__, __LINE__, 'We should find files with extension=' . $extension . ', but we found a PHP script. (baseFile=' . $baseFile . ')');
                        }
-               } elseif (substr($baseFile, -4, 4) == $extension) {
+               } elseif ($fileExtension == $extension) {
                        // Other, generic file found
                        $files[] = $fileName;
                }
@@ -2169,6 +2294,12 @@ function getArrayFromDirectory ($baseDir, $prefix, $fileIncludeDirs = false, $ad
        return $files;
 }
 
+// Checks wether $prefix is found in $fileName
+function isFilePrefixFound ($fileName, $prefix) {
+       // @TODO Find a way to cache this
+       return (substr($fileName, 0, strlen($prefix)) == $prefix);
+}
+
 // Maps a module name into a database table name
 function mapModuleToTable ($moduleName) {
        // Map only these, still lame code...
@@ -2290,7 +2421,10 @@ function getModuleFromFileName ($file, $accessLevel) {
 // Encodes an URL for adding session id, etc.
 function encodeUrl ($url, $outputMode = '0') {
        // Do we have already have a PHPSESSID inside or view.php is called? Then abort here
-       if ((strpos($url, session_name()) !== false) || (isRawOutputMode())) return $url;
+       if ((strpos($url, session_name()) !== false) || (isRawOutputMode())) {
+               // Raw output mode detected or session_name() found in URL
+               return $url;
+       } // END - if
 
        // Do we have a valid session?
        if (((!isset($GLOBALS['valid_session'])) || ($GLOBALS['valid_session'] === false) || (!isset($_COOKIE[session_name()]))) && (isSpider() === false)) {
@@ -2301,7 +2435,7 @@ function encodeUrl ($url, $outputMode = '0') {
                        // No question mark
                        $seperator = '?';
                } elseif ((!isHtmlOutputMode()) || ($outputMode != '0')) {
-                       // Non-HTML mode
+                       // Non-HTML mode (or forced non-HTML mode
                        $seperator = '&';
                }
 
@@ -2327,7 +2461,10 @@ function isSpider () {
        $userAgent = trim(strtolower(detectUserAgent(true)));
 
        // It should not be empty, if so it is better a spider/bot
-       if (empty($userAgent)) return true;
+       if (empty($userAgent)) {
+               // It is a spider/bot
+               return true;
+       } // END - if
 
        // Is it a spider?
        return ((strpos($userAgent, 'spider') !== false) || (strpos($userAgent, 'slurp') !== false) || (strpos($userAgent, 'bot') !== false) || (strpos($userAgent, 'archiver') !== false));
@@ -2421,7 +2558,7 @@ function capitalizeUnderscoreString ($str) {
                // "Walk" through all elements and make them lower-case but first upper-case
                foreach ($strArray as $part) {
                        // Capitalize the string part
-                       $capitalized .= ucfirst(strtolower($part));
+                       $capitalized .= firstCharUpperCase($part);
                } // END - foreach
 
                // Store the converted string in cache array
@@ -2432,10 +2569,103 @@ function capitalizeUnderscoreString ($str) {
        return $GLOBALS[__FUNCTION__][$str];
 }
 
+// Generate admin links for mail order
+// mailType can be: 'mid' or 'bid'
+function generateAdminMailLinks ($mailType, $mailId) {
+       // Init variables
+       $OUT = '';
+       $table = '';
+
+       // Default column for mail status is 'data_type'
+       // @TODO Rename column data_type to e.g. mail_status
+       $statusColumn = 'data_type';
+
+       // Which mail do we have?
+       switch ($mailType) {
+               case 'bid': // Bonus mail
+                       $table = 'bonus';
+                       break;
+
+               case 'mid': // Member mail
+                       $table = 'pool';
+                       break;
+
+               default: // Handle unsupported types
+                       logDebugMessage(__FUNCTION__, __LINE__, 'Unsupported mail type ' . $mailType . ' for mailId=' . $mailId . ' detected.');
+                       $OUT = '<div align="center">{%message,ADMIN_UNSUPPORTED_MAIL_TYPE_DETECTED=' . $mailType . '%}</div>';
+                       break;
+       } // END - switch
+
+       // Is the mail type supported?
+       if (!empty($table)) {
+               // Query for the mail
+               $result = SQL_QUERY_ESC("SELECT `id`, `%s` AS `mail_status` FROM `{?_MYSQL_PREFIX?}_%s` WHERE `id`=%s LIMIT 1",
+                       array($statusColumn, $table, bigintval($mailId)), __FILE__, __LINE__);
+
+               // Do we have one entry there?
+               if (SQL_NUMROWS($result) == 1) {
+                       // Load the entry
+                       $content = SQL_FETCHARRAY($result);
+                       die(__FUNCTION__.':<br />content=<pre>'.print_r($content, true).'</pre>');
+               } // END - if
+
+               // Free result
+               SQL_FREERESULT($result);
+       } // END - if
+
+       // Return generated HTML code
+       return $OUT;
+}
+
+
+/**
+ * determine if a string can represent a number in hexadecimal
+ *
+ * @param      $hex    A string to check if it is hex-encoded
+ * @return     $foo    True if the string is a hex, otherwise false
+ * @author     Marques Johansson
+ * @link       http://php.net/manual/en/function.http-chunked-decode.php#89786
+ */
+function isHexadecimal ($hex) {
+       // Make it lowercase
+       $hex = strtolower(trim(ltrim($hex, '0')));
+
+       // Fix empty strings to zero
+       if (empty($hex)) {
+               $hex = 0;
+       } // END - if
+
+       // Simply compare decode->encode result with original
+       return ($hex == dechex(hexdec($hex)));
+}
+
+// Replace "\r" with "[r]" and "\n" with "[n]" and add a final new-line to make
+// them visible to the developer. Use this function to debug e.g. buggy HTTP
+// response handler functions.
+function replaceReturnNewLine ($str) {
+       return str_replace("\r", '[r]', str_replace("\n", '[n]
+', $str));
+}
+
+// Converts a given string by splitting it up with given delimiter similar to
+// explode(), but appending the delimiter again
+function stringToArray ($delimiter, $string) {
+       // Init array
+       $strArray = array();
+
+       // "Walk" through all entries
+       foreach (explode($delimiter, $string) as $split) {
+               //  Append the delimiter and add it to the array
+               $strArray[] = $split . $delimiter;
+       } // END - foreach
+
+       // Return array
+       return $strArray;
+}
+
 //-----------------------------------------------------------------------------
 // Automatically re-created functions, all taken from user comments on www.php.net
 //-----------------------------------------------------------------------------
-//
 if (!function_exists('html_entity_decode')) {
        // Taken from documentation on www.php.net
        function html_entity_decode ($string) {
@@ -2454,7 +2684,9 @@ if (!function_exists('http_build_query')) {
                                $k = urlencode($prefix . $k);
                        } // END - if
 
-                       if ((!empty($key)) || ($key === 0))  $k = $key . '[' . urlencode($k) . ']';
+                       if ((!empty($key)) || ($key === 0)) {
+                               $k = $key . '[' . urlencode($k) . ']';
+                       } // END - if
 
                        if (is_array($v) || is_object($v)) {
                                array_push($ret, http_build_query($v, '', $sep, $k));
@@ -2463,11 +2695,112 @@ if (!function_exists('http_build_query')) {
                        }
                } // END - foreach
 
-               if (empty($sep)) $sep = ini_get('arg_separator.output');
+               if (empty($sep)) {
+                       $sep = ini_get('arg_separator.output');
+               } // END - if
 
                return implode($sep, $ret);
        }
 } // END - if
 
+if (!function_exists('http_chunked_decode')) {
+       /**
+        * dechunk an http 'transfer-encoding: chunked' message.
+        *
+        * @param       $chunk          The encoded message
+        * @return      $dechunk        The decoded message. If $chunk wasn't encoded properly debug_report_bug() is being called
+        * @author      Marques Johansson
+        * @link        http://php.net/manual/en/function.http-chunked-decode.php#89786
+        */
+       function http_chunked_decode ($chunk) {
+               // Init some variables
+               $offset = 0;
+               $len = mb_strlen($chunk);
+               $dechunk = '';
+
+               // Walk through all chunks
+               while ($offset < $len) {
+                       // Where does the \r\n begin?
+                       $lineEndAt = mb_strpos($chunk, getConfig('HTTP_EOL'), $offset);
+
+                       /* DEBUG: *
+                       print 'lineEndAt[<em>'.__LINE__.'</em>]='.$lineEndAt.'<br />
+offset[<em>'.__LINE__.'</em>]='.$offset.'<br />
+len='.$len.'<br />
+next[offset]=<pre>'.replaceReturnNewLine(htmlentities(mb_substr($chunk, $offset, 10))).'</pre>';
+                       /* DEBUG: */
+
+                       // Get next hex-coded chunk length
+                       $chunkLenHex = mb_substr($chunk, $offset, ($lineEndAt - $offset));
+
+                       /* DEBUG: *
+                       print 'chunkLenHex[<em>'.__LINE__.'</em>]='.replaceReturnNewLine(htmlentities($chunkLenHex)).'<br />
+';
+                       /* DEBUG: */
+
+                       // Validation if it is hexadecimal
+                       if (!isHexadecimal($chunkLenHex)) {
+                               // Please help debugging this
+                               //* DEBUG: */ die('ABORT:chunkLenHex=<pre>'.replaceReturnNewLine(htmlentities($chunkLenHex)).'</pre>');
+                               debug_report_bug(__FUNCTION__, __LINE__, 'Value ' . $chunkLenHex . ' is not properly chunk encoded.');
+
+                               // This won't be reached
+                               return $chunk;
+                       } // END - if
+
+                       // Position of next chunk is right after \r\n
+                       $offset   = $offset + strlen($chunkLenHex) + strlen(getConfig('HTTP_EOL'));
+                       $chunkLen = hexdec(rtrim($chunkLenHex, getConfig('HTTP_EOL')));
+
+                       /* DEBUG: *
+                       print 'chunkLen='.$chunkLen.'<br />
+offset[<em>'.__LINE__.'</em>]='.$offset.'<br />';
+                       /* DEBUG: */
+
+                       // Moved out for debugging
+                       $next  = mb_substr($chunk, $offset, $chunkLen);
+                       //* DEBUG: */ print 'next=<pre>'.replaceReturnNewLine(htmlentities($next)).'</pre>';
+
+                       // Count occurrences of \r\n
+                       $count = mb_substr_count($next, getConfig('HTTP_EOL'));
+
+                       // Correct it because we need to subtract occurrences of \r\n
+                       $chunkLen = hexdec(rtrim($chunkLenHex, getConfig('HTTP_EOL'))) - ($count * strlen(getConfig('HTTP_EOL')));
+
+                       $dechunk .= mb_substr($chunk, $offset, $chunkLen);
+
+                       /* DEBUG: *
+                       print('offset[<em>'.__LINE__.'</em>]='.$offset.'<br />
+lineEndAt[<em>'.__LINE__.'</em>]='.$lineEndAt.'<br />
+len='.$len.'<br />
+count='.$count.'<br />
+chunkLen='.$chunkLen.'<br />
+chunkLenHex='.$chunkLenHex.'<br />
+dechunk=<pre>'.replaceReturnNewLine(htmlentities($dechunk)).'</pre>
+chunk=<pre>'.replaceReturnNewLine(htmlentities($chunk)).'</pre>');
+                       /* DEBUG: */
+
+                       // Is $offset + $chunkLen larger than or equal $len?
+                       if (($offset + $chunkLen) >= $len) {
+                               // Then stop processing here
+                               break;
+                       } // END - if
+
+                       // Calculate next offset of chunk
+                       $offset = mb_strpos($chunk, getConfig('HTTP_EOL'), $offset + $chunkLen) + 2;
+
+                       /* DEBUG: *
+                       print('offset[<em>'.__LINE__.'</em>]='.$offset.'<br />
+next[100]=<pre>'.replaceReturnNewLine(htmlentities(mb_substr($chunk, $offset, 100))).'</pre>
+---:---:---:---:---:---:---:---:---<br />
+');
+                       /* DEBUG: */
+               } // END - while
+
+               // Return de-chunked string
+               return $dechunk;
+       }
+} // END - if
+
 // [EOF]
 ?>