X-Git-Url: https://git.mxchange.org/?p=mailer.git;a=blobdiff_plain;f=inc%2Fexpression-functions.php;h=9bd74b48cc5d8597a530457668ddb2b22641c38f;hp=c77eb0c92aec2bfca0887f262e79bc34119f92c6;hb=61621983cc6d7195fcc7eab29b5f6080ff283b34;hpb=d9f35786166902b9bc3f402d4f2abeed5ae0528d diff --git a/inc/expression-functions.php b/inc/expression-functions.php index c77eb0c92a..9bd74b48cc 100644 --- a/inc/expression-functions.php +++ b/inc/expression-functions.php @@ -10,16 +10,9 @@ * -------------------------------------------------------------------- * * Kurzbeschreibung : Expression-Callback-Funktionen * * -------------------------------------------------------------------- * - * $Revision:: $ * - * $Date:: $ * - * $Tag:: 0.2.1-FINAL $ * - * $Author:: $ * - * Needs to be in all Files and every File needs "svn propset * - * svn:keywords Date Revision" (autoprobset!) at least!!!!!! * - * -------------------------------------------------------------------- * * Copyright (c) 2003 - 2009 by Roland Haeder * - * Copyright (c) 2009, 2010 by Mailer Developer Team * - * For more information visit: http://www.mxchange.org * + * Copyright (c) 2009 - 2016 by Mailer Developer Team * + * For more information visit: http://mxchange.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 * @@ -42,25 +35,88 @@ if (!defined('__SECURITY')) { die(); } // END - if +// Private function to replace the code +function replaceExpressionCode ($data, $replacer) { + // Replace the code + // @TODO is escapeQuotes() enough for strings with single/double quotes? + return str_replace($data['matches'][0][$data['key']], $replacer, escapeQuotes($data['code'])); +} + +// Private function to determine whether we have a special expression function avaible +// (mostly located in wrapper-functions.php) +function isExpressionFunctionAvaiable ($data) { + // Get the enty we need and trim it + $entry = trim($data['matches'][4][$data['key']]); + + // Is there cache? + if (!isset($GLOBALS['expression_function_available'][$entry])) { + // Init function name + $functionName = 'get'; + + // Explode it in an array + foreach (explode('_', $entry) as $piece) { + // Add non-empty parts + if (!empty($piece)) { + // Add it + $functionName .= capitalizeUnderscoreString($piece); + } // END - if + } // END - foreach + + // Is that function there? + if (function_exists($functionName)) { + // Cache it all + $GLOBALS['expression_function_name'][$entry] = $functionName; + $GLOBALS['expression_function_available'][$entry] = TRUE; + } else { + // Not avaiable + logDebugMessage(__FUNCTION__, __LINE__, 'Expression function ' . $functionName . ' not found. Please consider adding it to improve execution speed.'); + + // And cache it + $GLOBALS['expression_function_available'][$entry] = FALSE; + } + } elseif (($GLOBALS['expression_function_available'][$entry] == FALSE) && (isDebugModeEnabled())) { + // Debug message in debug mode + logDebugMessage(__FUNCTION__, __LINE__, 'Expression function for entry ' . $entry . ' requested but does not exist.'); + } + + // Return cache + return $GLOBALS['expression_function_available'][$entry]; +} + +// Getter for above expression function +function getExpressionFunction ($data) { + // Get the enty we need + $entry = trim($data['matches'][4][$data['key']]); + + // Return it + return $GLOBALS['expression_function_name'][$entry]; +} + // Expression call-back function for getCode() calls function doExpressionCode ($data) { // Replace the code - $code = str_replace($data['matches'][0][$data['key']], "\" . getCode('" . $data['matches'][4][$data['key']] . "') . \"", $data['code']); + $code = str_replace($data['matches'][0][$data['key']], "{DQUOTE} . getCode('" . $data['matches'][4][$data['key']] . "') . {DQUOTE}", $data['code']); // Return replaced code return $code; } -// Expression call-back function for URLs +// Expression call-back function for URLs (example: {%url=foo.php?bar=bar%}) function doExpressionUrl ($data) { - // Do we have JS-mode? - if ($data['callback'] == 'js') $data['mode'] = 1; + // Is there JS-mode? + if ($data['callback'] == 'js') { + // Switch to it + $data['output_mode'] = '1'; + } // END - if // Handle an URL here - $replacer = "\" . encodeUrl(\"" . $data['matches'][4][$data['key']] . "\", " . $data['mode'] . ") . \""; + $replacer = "{DQUOTE} . encodeUrl('" . $data['matches'][4][$data['key']] . "', " . $data['output_mode'] . ') . {DQUOTE}'; + + // Debug log + //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'replacer=' . $replacer . ',callback=' . $data['callback'] . ',output_mode=' . $data['output_mode']); // Replace it - $code = str_replace($data['matches'][0][$data['key']], $replacer, $data['code']); + $code = replaceExpressionCode($data, $replacer); // Return replaced code return $code; @@ -69,43 +125,13 @@ function doExpressionUrl ($data) { // Expression call-back function for reading data from $_SERVER function doExpressionServer ($data) { // This will make 'foo_bar' to detectFooBar() - $functionName = "'detect' . implode('', array_map('ucfirst', explode('_', '" . $data['callback'] . "')))"; - - // Replace it - $code = str_replace($data['matches'][0][$data['key']], "\" . call_user_func(" . $functionName . ") . \"", $data['code']); + $functionName = "'detect' . implode('', array_map('firstCharUpperCase', explode('_', '" . $data['callback'] . "')))"; - // Return replaced code - return $code; -} - -// Expression call-back function for fetching user data -function doExpressionUser ($data) { - // Use current userid by default - $functionName = 'getMemberId()'; - - // User-related data, so is there a userid? - if (!empty($data['matches'][4][$data['key']])) { - // Do we have a userid or $userid? - if ($data['matches'][4][$data['key']] == '$userid') { - // Use dynamic call - $functionName = "getFetchedUserData('userid', \$userid, '" . $data['callback'] . "')"; - } elseif ($data['matches'][4][$data['key']] > 0) { - // User data found - $functionName = "getFetchedUserData('userid', " . $data['matches'][4][$data['key']] . ", " . $data['callback'] . "')"; - } - } elseif ((!empty($data['callback'])) && (isUserDataValid())) { - // "Call-back" alias column for current logged in user's data - $functionName = "getUserData('" . $data['callback'] . "')"; - } - - // Do we have another function to run (e.g. translations) - if (!empty($data['extra_func'])) { - // Surround the original function call with it - $functionName = $data['extra_func'] . '(' . $functionName . ')'; - } // END - if + // Generate replacer + $replacer = '{DQUOTE} . call_user_func(' . $functionName . ') . {DQUOTE}'; - // Now replace the code - $code = str_replace($data['matches'][0][$data['key']], "\" . " . $functionName . " . \"", $data['code']); + // Replace it + $code = replaceExpressionCode($data, $replacer); // Return replaced code return $code; @@ -119,14 +145,20 @@ function doExpressionExt ($data) { // Is the extension installed? if (isExtensionInstalled($data['matches'][4][$data['key']])) { // Construct call-back function name - $functionName = 'getExtension' . ucfirst(strtolower($data['callback'])); + $functionName = 'getExtension' . capitalizeUnderscoreString($data['callback']); // Construct call of the function - $replacer = "\" . call_user_func_array('" . $functionName . "', array('" . $data['matches'][4][$data['key']] . "', true)) . \""; + $replacer = "{DQUOTE} . call_user_func_array('" . $functionName . "', array('" . $data['matches'][4][$data['key']] . "', TRUE)) . {DQUOTE}"; } // END - if + // Generate replacer + $replacer = sprintf('&ext=%s&ver=%s', $data['matches'][4][$data['key']], $replacer); + // Replace it and insert parameter for GET request - $code = str_replace($data['matches'][0][$data['key']], sprintf("&ext=%s&ver=%s&rev=\" . getConfig('CURR_SVN_REVISION') . \"", $data['matches'][4][$data['key']], $replacer), $data['code']); + $code = replaceExpressionCode($data, $replacer); + + // Debug message + //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'code=' . $code . ',replacer=' . $replacer . ',key=' . $data['key'] . ',callback=' . $data['callback']); // Return replaced code return $code; @@ -135,14 +167,20 @@ function doExpressionExt ($data) { // Expression call-back function for getting configuration data // @TODO FILTER_COMPILE_CONFIG does not handle call-back functions so we handle it here again function doExpressionConfig ($data) { - // Read configuration - $configValue = getConfig($data['matches'][4][$data['key']]); - - // Construct a new expression - $replacer = '{%pipe,' . $data['callback'] . ',' . $configValue . '%}'; + // Is there a special expression function for it? + if (isExpressionFunctionAvaiable($data)) { + // Then use it + $replacer = '{DQUOTE} . ' . $data['callback'] . '(' . getExpressionFunction($data) . '()) . {DQUOTE}'; + } elseif (!isConfigEntrySet($data['matches'][4][$data['key']])) { + // Config entry is not set + $replacer = '{DQUOTE} . ' . $data['callback'] . '(NULL) . {DQUOTE}'; + } else { + // Default replacer is the config value itself + $replacer = '{DQUOTE} . ' . $data['callback'] . '(getConfig(' . chr(39) . $data['matches'][4][$data['key']] . chr(39) . ')) . {DQUOTE}'; + } // Replace the config entry - $code = str_replace($data['matches'][0][$data['key']], $replacer, $data['code']); + $code = replaceExpressionCode($data, $replacer); // Return replaced code return $code; @@ -153,14 +191,26 @@ function doExpressionPipe ($data) { // We need callback and extra_func: callback is really the call-back function, extra_func is our value $replacer = $data['extra_func']; - // Do we have a call-back? Should always be there! + // Is there a call-back? Should always be there! if (!empty($data['callback'])) { - // Parse it through this function - $replacer = "\" . " . $data['callback'] . "('" . $replacer . "') . \""; + //* DEBUG: */ if ($data['callback'] == 'getMemberId') die('
'.encodeEntities(print_r($data, TRUE)).'
'); + // If the value is empty, we don't add it + //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value[' . gettype($data['value']) . ']=' . $data['value']); + if ((empty($data['value'])) && ($data['value'] != '0')) { + // No value is set + $replacer = '{DQUOTE} . ' . $data['extra_func2'] . '(' . $data['extra_func'] . '(' . $data['callback'] . '())) . {DQUOTE}'; + } elseif (isXmlTypeBool($data['value'])) { + // Boolean value detected + $replacer = '{DQUOTE} . ' . $data['extra_func2'] . '(' . $data['extra_func'] . '(' . $data['callback'] . '(' . $data['value'] . '))) . {DQUOTE}'; + } else { + // Some string/integer value is set + $replacer = '{DQUOTE} . ' . $data['extra_func2'] . '(' . $data['extra_func'] . '(' . $data['callback'] . "('" . $data['value'] . "'))) . {DQUOTE}"; + } } // END - if // Replace the config entry - $code = str_replace($data['matches'][0][$data['key']], $replacer, $data['code']); + //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'replacer=' . $replacer); + $code = replaceExpressionCode($data, $replacer); // Return replaced code return $code; @@ -169,10 +219,10 @@ function doExpressionPipe ($data) { // Expression call-back function for calling filters function doExpressionFilter ($data) { // Construct replacement - $replacer = "\" . runFilterChain('" . $data['matches'][4][$data['key']] . "') . \""; + $replacer = "{DQUOTE} . runFilterChain('" . $data['matches'][4][$data['key']] . "') . {DQUOTE}"; // Run the filter and insert result - $code = str_replace($data['matches'][0][$data['key']], $replacer, $data['code']); + $code = replaceExpressionCode($data, $replacer); // Return replaced code return $code; @@ -189,11 +239,11 @@ function doExpressionValidatorLinks ($data) { // Should we generally include validator links? if ((isExtensionInstalled('validator')) && (getConfig('enable_validator') == 'Y') && (!in_array(getModule(), array('admin', 'login')))) { // Load the validator template - $replacer = escapeQuotes(loadTemplate('validator_links', true)); + $replacer = escapeQuotes(loadTemplate('validator_links', TRUE)); } // END - if // Replace the code - $code = str_replace($data['matches'][0][$data['key']], $replacer, $code); + $code = replaceExpressionCode($data, $replacer); // Return the (maybe) replaced code return $code; @@ -201,18 +251,303 @@ function doExpressionValidatorLinks ($data) { // Expression call-back for dynamic messages function doExpressionMessage ($data) { + // Debug message + //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'callback=' . $data['callback'] . ',extra_func=' . $data['extra_func'] . ',value=' . $data['value']); + // Message string replacement depends on if message is masked - if (isMessageMasked($data['callback'])) { + if ((isMessageMasked($data['callback'], FALSE)) && ((!empty($data['extra_func'])) || ($data['extra_func'] == '0'))) { // Message should be masked - $replacer = "\" . getMaskedMessage('" . $data['callback'] . "', '" . $data['extra_func'] . "') . \""; + $replacer = "{DQUOTE} . getMaskedMessage('" . $data['callback'] . "', '" . $data['extra_func'] . "') . {DQUOTE}"; + } elseif (!empty($data['value'])) { + // value is set, so it is masked message + $replacer = "{DQUOTE} . getMaskedMessage('" . $data['callback'] . "', '" . $data['value'] . "') . {DQUOTE}"; } else { // Regular message - $replacer = "\" . getMessage('" . $data['callback'] . "') . \""; + $replacer = "{DQUOTE} . getMessage('" . $data['callback'] . "') . {DQUOTE}"; + } + + // Replace the code + $code = replaceExpressionCode($data, $replacer); + + // Return the (maybe) replaced code + return $code; +} + +// Expression call-back for template functions +function doExpressionTemplate ($data) { + // Construct call-back function name + $callbackFunction = 'doTemplate' . ucfirst($data['callback']); + + // Init replacer + $replacer = ''; + + // Is the function there? + if (!isset($GLOBALS['current_template'])) { + // This is very bad and needs fixing + reportBug(__FUNCTION__, __LINE__, 'current_template in GLOBALS not set, callbackFunction=' . $callbackFunction . ',function_exists()=' . intval(function_exists($callbackFunction))); + } elseif (!function_exists($callbackFunction)) { + // Log missing function only in debug mode + if (isDebugModeEnabled()) { + // Log it here + logDebugMessage(__FUNCTION__, __LINE__, 'Call-back function ' . $callbackFunction . ' does not exist.'); + } // END - if + } else { + // Do the replacement + //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'template='.$GLOBALS['current_template']); + $replacer = '{DQUOTE} . ' . $callbackFunction . '(' . chr(39) . $GLOBALS['current_template'] . chr(39) . ', TRUE'; + + // Is 'value' set? + if (!empty($data['value'])) { + // Then include it as well + $replacer .= ', ' . chr(39) . $data['value'] . chr(39); + } // END - if + + // Replacer is ready + $replacer .= ') . {DQUOTE}'; } // Replace the code - // @TODO is escapeQuotes enougth for strings with single/double quotes? - $code = str_replace($data['matches'][0][$data['key']], $replacer, escapeQuotes($data['code'])); + $code = replaceExpressionCode($data, $replacer); + + // Return the (maybe) replaced code + return $code; +} + +// Expression call-back for math functions +function doExpressionMath ($data) { + // Do the replacement + //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'template='.$GLOBALS['current_template']); + $replacer = '{DQUOTE} . doCalculate' . $data['callback'] . '(' . $data['value'] . ') . {DQUOTE}'; + + // Replace the code + $code = replaceExpressionCode($data, $replacer); + + // Load include once + loadIncludeOnce('inc/math-functions.php'); + + // Return the (maybe) replaced code + return $code; +} + +// Expression call-back for GET request +function doExpressionGet ($data) { + // Construct the replacer: + // - GET request element + $replacer = '{%pipe,getRequestElement'; + + // Add more call-back functions? + if (!empty($data['callback'])) { + // - Okay, add them + $replacer .= ',' . $data['callback']; + } // END - if + + // - Finalize replacer + $replacer .= '=' . $data['value'] . '%}'; + + // Replace the code + $code = replaceExpressionCode($data, $replacer); + + // Return the (maybe) replaced code + return $code; +} + +// Expression call-back for POST request +function doExpressionPost ($data) { + // Construct the replacer: + // - POST request element + $replacer = '{%pipe,postRequestElement'; + + // Add more call-back functions? + if (!empty($data['callback'])) { + // - Okay, add them + $replacer .= ',' . $data['callback']; + } // END - if + + // - Finalize replacer + $replacer .= '=' . $data['value'] . '%}'; + + // Replace the code + $code = replaceExpressionCode($data, $replacer); + + // Return the (maybe) replaced code + return $code; +} + +// Expression call-back for session data +function doExpressionSession ($data) { + // Construct the replacer: + // - Session element + $replacer = '{%pipe,getSession'; + + // Add more call-back functions? + if (!empty($data['callback'])) { + // - Okay, add them + $replacer .= ',' . $data['callback']; + } // END - if + + // - Finalize replacer + $replacer .= '=' . $data['value'] . '%}'; + + // Debug message + //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $data['value'] . ',replacer=' . $replacer); + + // Replace the code + $code = replaceExpressionCode($data, $replacer); + + // Return the (maybe) replaced code + return $code; +} + +/** + * Expression call-back for session piplining, this means: + * + * 1) Read session data + * 2) Wrap the raw data into {%pipe,fooFunction=$rawValue%} + */ +function doExpressionSessionPipe ($data) { + // Get the session data + $rawValue = getSession($data['value']); + + // Construct the replacer + $replacer = '{%pipe,' . $data['callback'] . '=' . $rawValue . '%}'; + + // Debug message + //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $data['value'] . ',rawValue=' . $rawValue . ',replacer=' . $replacer); + + // Replace the code + $code = replaceExpressionCode($data, $replacer); + + // Return the (maybe) replaced code + return $code; +} + +// Expression call-back for formulars +function doExpressionForm ($data) { + // Default method is GET, target is _self + $data['__form_method'] = 'get'; + $data['__form_target'] = '_self'; + $data['__form_name'] = 'form'; + $data['__form_id'] = 'form'; + $data['__server'] = ''; + + // Check which method/target is set + foreach (array('callback', 'extra_func', 'extra_func2') as $key) { + // Make lower-case + $value = strtolower($data[$key]); + + // Is formMethodPost set? + if ($value == 'formmethodpost') { + // Use it + $data['__form_method'] = 'post'; + } elseif (($value == 'formmethodpost') && (!isSpider()) && (!isValidSession())) { + // Then expand 'value' with session id + if (strpos($data['value'], '?') !== FALSE) { + // '?' is set + $data['value'] .= '&'; + } else { + // Is not set + $data['value'] .= '?'; + } + + // Append session's name and id + $data['value'] .= session_name() . '=' . session_id(); + } elseif (substr($value, 0, 10) == 'formtarget') { + // Form target is found + $data['__form_target'] = substr($value, 10); + } elseif (substr($value, 0, 8) == 'formname') { + // Form name is found + $data['__form_name'] = substr($value, 8); + } elseif (substr($value, 0, 6) == 'formid') { + // Form id found + $data['__form_id'] = substr($value, 6); + } elseif (substr($value, 0, 6) == 'server') { + // {%server,foo%} found + $data['__server'] = '{%server,' . substr($value, 6) . '%}'; + } + } // END - foreach + + // Generate the replacement code which is the opening form tag + $data['__replacer'] = '' . PHP_EOL; + + /* + * Call a filter chain to allow more hidden fields being added at the end + * of the form. + */ + $data = runFilterChain('close_form_fields', $data); + + // Replace the code + $code = replaceExpressionCode($data, $data['__replacer']); + + // Return the (maybe) replaced code + return $code; +} + +// Expression call-back to handle jquery inclusion +function doExpressionJquery ($data) { + // Default is compressed + $jquery = 'jquery'; + $data['output_mode'] = ''; + + // Is there JS-mode? + if ($data['callback'] == 'js') { + // Switch to it + $data['output_mode'] = ',js'; + } // END - if + + // Is there a value? + if ($data['callback'] == 'js') { + // Then load special library + $jquery .= '-' . $data['value']; + } // END - if + + // Is debug mode enabled? + if ((isGetRequestElementSet('jquery')) || (isSessionVariableSet('jquery'))) { + // Then use uncompressed + $jquery .= '.uncompressed'; + + // Remember it in session + setSession('jquery', '1'); + } // END - if + + // Add {%url%} around it + $replacer = '{%url' . $data['output_mode'] . '=js/' . $jquery . '.js?dummy=1%}'; + + // Replace the code + $code = replaceExpressionCode($data, $replacer); // Return the (maybe) replaced code return $code;