' . $message . '');
}
// "Fixes" an empty string into three dashes (use for templates)
function fixEmptyContentToDashes ($str) {
// Call inner function
$str = fixNullEmptyToDashes($str, 3);
// Return string
return $str;
}
// Init color switch
function initTemplateColorSwitch ($template) {
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'INIT:' . $template);
$GLOBALS['color_switch'][$template] = 2;
}
// "Getter" for color switch code
function getColorSwitchCode ($template) {
// Prepare the code
$code = "{DQUOTE} . doTemplateColorSwitch('" . $template . "', FALSE, FALSE) . {DQUOTE}";
// And return it
return $code;
}
// Output HTML code directly or 'render' it. You addionally switch the new-line character off
function outputHtml ($htmlCode = NULL, $newLine = TRUE) {
// Init output
if (!isset($GLOBALS['__output'])) {
$GLOBALS['__output'] = '';
} // END - if
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getOutputMode()=' . getOutputMode() . ',htmlCode(length)=' . strlen($htmlCode) . ',output(length)=' . strlen($GLOBALS['__output']));
// Is there HTML-Code here?
if ((!is_null($htmlCode)) && (!empty($htmlCode))) {
// Yes, so we handle it as you have configured
switch (getOutputMode()) {
case 'render':
// But if PHP is caching, then we don't need to do that
if (getPhpCaching() == 'on') {
// Output into PHP's internal buffer
outputRawCode($htmlCode);
// That's why you don't need any \n at the end of your HTML code... :-)
if ($newLine === TRUE) {
outputRawCode(PHP_EOL);
} // END - if
} else {
// Render mode for old or lame servers...
$GLOBALS['__output'] .= $htmlCode;
// That's why you don't need any \n at the end of your HTML code... :-)
if ($newLine === TRUE) {
$GLOBALS['__output'] .= PHP_EOL;
} // END - if
}
break;
case 'direct':
// If we are switching from 'render' to 'direct' mode, all data in '__output' must be flushed and cleared
if ((!empty($GLOBALS['__output'])) && (getPhpCaching() != 'on')) {
outputRawCode($GLOBALS['__output']);
$GLOBALS['__output'] = '';
} // END - if
// The same as above... ^
outputRawCode($htmlCode);
if ($newLine === TRUE) {
outputRawCode(PHP_EOL);
} // END - if
break;
default:
// Huh, something goes wrong or maybe you have edited config.php ???
reportBug(__FUNCTION__, __LINE__, '{--FATAL_ERROR--}: {--NO_RENDER_DIRECT--}');
break;
} // END - switch
} elseif ((getPhpCaching() == 'on') && (!isFilledArray($GLOBALS['http_header'])) && (!isRawOutputMode())) {
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getPhpCaching()=' . getPhpCaching() . ',isset(http_header)=' . intval(isset($GLOBALS['http_header'])) . ',getScriptOutputMode()=' . getScriptOutputMode() . '');
// Output cached HTML code
$GLOBALS['__output'] = ob_get_contents();
// Clear output buffer for later output if output is found
if (!empty($GLOBALS['__output'])) {
clearOutputBuffer();
} // END - if
// Send all HTTP headers
sendHttpHeaders();
// Compile and run finished rendered HTML code
compileFinalOutput();
// Output code here, DO NOT REMOVE! ;-)
outputRawCode($GLOBALS['__output']);
} elseif ((getOutputMode() == 'render') && (!empty($GLOBALS['__output'])) && (!isRawOutputMode())) {
// Send all HTTP headers
sendHttpHeaders();
// Compile and run finished rendered HTML code
compileFinalOutput();
// Output code here, DO NOT REMOVE! ;-)
outputRawCode($GLOBALS['__output']);
} else {
// And flush all headers
flushHttpHeaders();
}
}
// Compiles the final output
function compileFinalOutput () {
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, '__output(length)=' . strlen($GLOBALS['__output']) . ',getScriptOutputMode()=' . getScriptOutputMode() . ' - ENTERED!');
// Is this function called?
if (isset($GLOBALS[__FUNCTION__])) {
// Abort here
reportBug(__FUNCTION__, __LINE__, 'Double call of ' . __FUNCTION__ . ' causes problems with sent headers.');
} // END - if
// Mark this function as called
$GLOBALS[__FUNCTION__] = TRUE;
// Add page header and footer
addPageHeaderFooter();
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, '__output(length)=' . strlen($GLOBALS['__output']) . ' - After addPageHeaderFooter() call.');
// Do the final (general) compilation
$GLOBALS['__output'] = doFinalCompilation($GLOBALS['__output']);
// Compile any other things out
$GLOBALS['__output'] = compileUriCode($GLOBALS['__output']);
// Extension 'rewrite' installed?
if ((isExtensionActive('rewrite')) && (!isCssOutputMode())) {
$GLOBALS['__output'] = rewriteLinksInCode($GLOBALS['__output']);
} // END - if
// Compress it?
/**
* @TODO On some pages this is buggy
if (!empty($_SERVER['HTTP_ACCEPT_ENCODING']) && (isInStringIgnoreCase('gzip', $_SERVER['HTTP_ACCEPT_ENCODING']))) {
// Compress it for HTTP gzip
$GLOBALS['__output'] = gzencode($GLOBALS['__output'], 9);
// Add header
addHttpHeader('Content-Encoding: gzip');
} elseif (!empty($_SERVER['HTTP_ACCEPT_ENCODING']) && (isInStringIgnoreCase('deflate', $_SERVER['HTTP_ACCEPT_ENCODING']))) {
// Compress it for HTTP deflate
$GLOBALS['__output'] = gzcompress($GLOBALS['__output'], 9);
// Add header
addHttpHeader('Content-Encoding: deflate');
}
*/
// Add final length
addHttpHeader('Content-Length: ' . strlen($GLOBALS['__output']));
// Flush all headers
flushHttpHeaders();
}
// Main compilation loop
function doFinalCompilation ($code, $insertComments = TRUE, $enableCodes = TRUE) {
// Insert comments? (Only valid with HTML templates, of course)
enableTemplateHtml($insertComments);
// Init counter
$totalCompilations = 0;
// Compile all out
while (((isInString('{--', $code)) || (isInString('{DQUOTE}', $code)) || (isInString('{?', $code)) || (isInString('{%', $code) !== FALSE)) && ($totalCompilations < 7)) {
// Init common variables
$content = array();
$newContent = '';
// Compile it
//* DEBUG: */ debugOutput('
');
eval($GLOBALS['template_eval']['html'][$template]);
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'template=' . $template . ' - AFTER EVAL');
} // END - if
// Is there some content to output or return?
if ((empty($templateContent)) && (isDebugModeEnabled())) {
// Warning, empty output!
return 'E:' . $template . ',content=
' . print_r($content, TRUE) . '
';
} // END - if
// Not empty so let's put it out! ;)
if ($return === TRUE) {
// Return the HTML code
return $templateContent;
} else {
// Output directly
outputHtml($templateContent);
}
}
// Detects the extra template path from given template name
function detectExtraTemplatePath ($prefix, $template) {
// Default is empty
$extraPath = '';
// Is there cache?
if (!isset($GLOBALS['extra_path'][$prefix][$template])) {
// Check for admin/guest/member/etc. templates
if (substr($template, 0, 6) == 'admin_') {
// Admin template found
$extraPath = 'admin/';
} elseif (substr($template, 0, 6) == 'guest_') {
// Guest template found
$extraPath = 'guest/';
} elseif (substr($template, 0, 7) == 'member_') {
// Member template found
$extraPath = 'member/';
} elseif (substr($template, 0, 7) == 'select_') {
// Selection template found
$extraPath = 'select/';
} elseif (substr($template, 0, 8) == 'install_') {
// Installation template found
$extraPath = 'install/';
} elseif (substr($template, 0, 4) == 'ext_') {
// Extension template found
$extraPath = 'ext/';
} elseif (substr($template, 0, 3) == 'la_') {
// 'Logical-area' template found
$extraPath = 'la/';
} elseif (substr($template, 0, 3) == 'js_') {
// JavaScript template found
$extraPath = 'js/';
} elseif (substr($template, 0, 5) == 'menu_') {
// Menu template found
$extraPath = 'menu/';
} else {
// Test for extension
$test = substr($template, 0, strpos($template, '_'));
// Probe for valid extension name
if (isExtensionNameValid($test)) {
// Set extra path to extension's name
$extraPath = $test . '/';
} // END - if
}
// Store it in cache
$GLOBALS['extra_path'][$prefix][$template] = $extraPath;
} // END - if
// Return result
return $GLOBALS['extra_path'][$prefix][$template];
}
// Loads an email template and compiles it
function loadEmailTemplate ($template, $content = array(), $userid = NULL, $loadUserData = TRUE) {
// Make sure all template names are lowercase!
$template = strtolower($template);
// Set current template
$GLOBALS['current_template'] = $template;
// Is content an array?
if (is_array($content)) {
// Add expiration to array
if ((isExtensionInstalled('autopurge')) && (isConfigEntrySet('auto_purge')) && (getAutoPurge() == '0')) {
// Will never expire!
$content['expiration'] = '{--MAIL_WILL_NEVER_EXPIRE--}';
} elseif ((isExtensionInstalled('autopurge')) && (isConfigEntrySet('auto_purge'))) {
// Create nice date string
$content['expiration'] = '{%config,createFancyTime=auto_purge%}';
} else {
// Missing entry
$content['expiration'] = '{--MAIL_NO_CONFIG_AUTO_PURGE--}';
}
} // END - if
// Is there cache?
if ((!isDebugTemplateCacheEnabled()) && (isTemplateCached('email', $template))) {
// Evaluate the cache
$templateContent = readTemplateCache('email', $template, $content);
// Better remove array element which is need only in uncached mode
unset($GLOBALS['template_eval']['email'][$template]);
} elseif (!isset($GLOBALS['template_eval']['email'][$template])) {
// Base directory
$basePath = getTemplateBasePath('emails');
// Detect extra path
$extraPath = detectExtraTemplatePath('email', $template);
// Generate full FQFN
$FQFN = $basePath . '/' . $extraPath . $template . '.tpl';
// Does the special template exists?
if (!isFileReadable($FQFN)) {
// Reset to default template
$FQFN = $basePath . '/' . $template . '.tpl';
} // END - if
// Now does the final template exists?
$templateContent = '';
if (isFileReadable($FQFN)) {
// The local file does exists so we load it. :)
$GLOBALS['template_content']['email'][$template] = readFromFile($FQFN);
// Run code
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Reached!');
$GLOBALS['template_eval']['email'][$template] = '$templateContent = decodeEntities("' . compileRawCode(escapeQuotes($GLOBALS['template_content']['email'][$template])) . '");';
} elseif (!empty($template)) {
// Template file not found
$templateContent = '
{--TEMPLATE_404--}: ' . $template . '
{--TEMPLATE_CONTENT--}:
' . print_r($content, TRUE) . '
';
// Don't cache this, as there is no template to cache
$GLOBALS['template_eval']['email'][$template] = '404';
// Debug mode not active? Then remove the HTML tags
if (!isDebugModeEnabled()) {
// Remove HTML tags
$templateContent = secureString($templateContent);
} // END - if
} else {
// No template name supplied!
$templateContent = '{--NO_TEMPLATE_SUPPLIED--}';
$GLOBALS['template_eval']['email'][$template] = '404';
}
}
// Is there something to eval?
if ((isset($GLOBALS['template_eval']['email'][$template])) && ($GLOBALS['template_eval']['email'][$template] != '404')) {
// Eval the code
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'template=' . $template . ' - BEFORE EVAL');
//* DEBUG: */ print('
');
eval($GLOBALS['template_eval']['email'][$template]);
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'template=' . $template . ' - AFTER EVAL');
} // END - if
// Are there some content?
if (empty($templateContent)) {
// Compiling failed
$templateContent = "Compiler error for template " . $template . " !\nUncompiled content:\n" . $GLOBALS['template_eval']['email'][$template];
// Add last error if the required function exists
if (function_exists('error_get_last')) {
// Add last error and some lines for better overview
$templateContent .= "\n--------------------------------------\nDebug:\n" . print_r(error_get_last(), TRUE) . "--------------------------------------\nPlease don't alter these informations!\nThanx.";
} // END - if
} // END - if
// Remove content and data
unset($content);
// Return content
return $templateContent;
}
// "Getter" for menu CSS classes, mainly used in templates
function getMenuCssClasses ($data) {
//* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'data=' . $data);
// Is there cache?
if (!isset($GLOBALS[__FUNCTION__][$data])) {
// $data needs to be converted into an array
$content = explode('|', $data);
// Non-existent index 2 will happen in menu blocks
if (!isset($content[2])) {
$content[2] = '';
} // END - if
// Re-construct the array: 0=visible,1=locked,2=prefix
$content['visible'] = $content[0];
$content['locked'] = $content[1];
// Call our "translator" function
$content = translateMenuVisibleLocked($content, $content[2]);
// Set it in cache
$GLOBALS[__FUNCTION__][$data] = ($content['visible_css'] . ' ' . $content['locked_css']);
} // END - if
// Return cache
return $GLOBALS[__FUNCTION__][$data];
}
// Generate XHTML code for the CAPTCHA
function generateCaptchaCode ($code, $type, $urlId, $userid) {
return '';
}
// Compiles the given HTML/mail code
function compileCode ($code, $full = TRUE, $compileCode = TRUE) {
// Is the code a string or should we not compile?
if ((!is_string($code)) || ($compileCode === FALSE)) {
// Silently return it
return $code;
} // END - if
// Start couting
$startCompile = microtime(TRUE);
// Comile the code
$code = compileRawCode($code, $full, $compileCode);
// Get timing
$compilationTime = $startCompile - microtime(TRUE);
// Add timing if enabled
if (isTemplateHtml()) {
// Add timing, this should be disabled in
$code .= '';
} // END - if
// Return compiled code
return $code;
}
// Compiles the code
function compileRawCode ($code, $full = TRUE, $compileCode = TRUE) {
// Is the code a string or shall we not compile?
if ((!is_string($code)) || ($compileCode === FALSE)) {
// Silently return it
return $code;
} // END - if
// Init replacement-array with smaller set of security characters
$secChars = $GLOBALS['url_chars'];
// Select full set of chars to replace when we e.g. want to compile URLs
if ($full === TRUE) {
$secChars = $GLOBALS['security_chars'];
} // END - if
// Compile more through a filter
$code = runFilterChain('compile_code', $code);
// First compile these chars
array_unshift($secChars['to'] , '{--' , '--}');
array_unshift($secChars['from'], '{%message,', '%}' );
// Compile QUOT and other non-HTML codes
$code = str_replace($secChars['to'], $secChars['from'], $code);
// Find $content[bla][blub] entries
preg_match_all('/\$content((\[([a-zA-Z0-9-_]+)\])*)/', $code, $matches);
//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Second regex gave ' . count($matches[0]) . ' matches.');
// Are some matches found?
if ((isFilledArray($matches)) && (isFilledArray($matches[0]))) {
// Replace all matches
$matchesFound = array();
foreach ($matches[0] as $key => $match) {
// Fuzzy look has failed by default
$fuzzyFound = FALSE;
// "Cache" match length
$matchLength = strlen($match);
// Fuzzy look on match if already found
foreach ($matchesFound as $found => $set) {
// Get test part
$test = substr($found, 0, $matchLength);
// Does this entry exist?
//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'found=' . $found . ',match=' . $match . ',set=' . $set);
if ($test == $match) {
// Match found
//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'fuzzyFound!');
$fuzzyFound = TRUE;
break;
} // END - if
} // END - foreach
// Skip this entry?
if ($fuzzyFound === TRUE) {
continue;
} // END - if
// Take all string elements
if ((is_string($matches[3][$key])) && (!isset($matchesFound[$match])) && (!isset($matchesFound[$key.'_' . $matches[3][$key]]))) {
// Replace it in the code, replace dollar sign so it won't be detected by next regex (see there)
//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',match=' . $match);
$newMatch = str_replace(array('[', ']', '$'), array("['", "']", '{COMPILE_DOLLAR}'), $match);
$code = str_replace($match, '".' . $newMatch . '."', $code);
$matchesFound[$key . '_' . $matches[3][$key]] = 1;
$matchesFound[$match] = TRUE;
} elseif (!isset($matchesFound[$match])) {
// Not yet replaced!
//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'match=' . $match);
$code = str_replace($match, '".' . $match . '."', $code);
$matchesFound[$match] = 1;
} else {
// Everthing else should be a least logged
logDebugMessage(__FUNCTION__, __LINE__, 'match=' . $match . ',key=' . $key);
}
} // END - foreach
} // END - if
/*
* Find $foobar, $foo_bar and $fooBar entries. This regex would also find
* $content[foo_bar] which would result in {DOLLAR}content[foo_bar] and
* therefore the variable's value won't be inserted. This is why
* {COMPILE_DOLLAR} is being used in above loop and at the end of this
* function being replace with the original dollar sign again.
*/
preg_match_all('/\$([a-z_A-Z\[\]]){0,}/', $code, $matches);
// Are some matches found?
if ((isFilledArray($matches)) && (isFilledArray($matches[0]))) {
// Scan all matches for not $content
foreach ($matches[0] as $match) {
// Trim match
$match = trim($match);
// Debug message
//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'match=' . $match);
// Is the first part not $content/$userid and not empty?
// @TODO $userid is deprecated and should be removed from loadEmailTemplate() and replaced with $content[userid] in all templates
if ((!empty($match)) && (substr($match, 0, 8) != '$content') && ($match != '$userid')) {
//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'match=' . $match . ' - SECURED!');
// Then replace $ with {DOLLAR}
$matchSecured = str_replace('$', '{DOLLAR}', $match);
// And in $code as well
$code = str_replace($match, $matchSecured, $code);
} // END - if
} // END - if
} // END - if
// Replace {COMPILE_DOLLAR} back to dollar sign
$code = str_replace('{COMPILE_DOLLAR}', '$', $code);
// Finally return it
return $code;
}
//
function addSelectionBox ($type, $default, $prefix = '', $id = NULL, $class = 'form_select') {
$OUT = '';
if ($type == 'yn') {
// This is a yes/no selection only!
if (isValidId($id)) $prefix .= '[' . $id . ']';
$OUT .= '