<?php /*+********************************************************************************** * The contents of this file are subject to the vtiger CRM Public License Version 1.1 * ("License"); You may not use this file except in compliance with the License * The Original Code is: vtiger CRM Open Source * The Initial Developer of the Original Code is vtiger. * Portions created by vtiger are Copyright (C) vtiger. * All Rights Reserved. ************************************************************************************/ sphere_import ('~/lib/Smarty/libs/SmartyBC.class.php'); class Sphere_Viewer extends SmartyBC { const DEFAULTLAYOUT = 'slayout'; const DEFAULTTHEME = 'softed'; static $currentLayout; // Turn-it on to analyze the data pushed to templates for the request. protected static $debugViewer = false; /** * log message into the file if in debug mode. * @param type $message * @param type $delimiter */ protected function log($message, $delimiter="\n") { static $file = null; if ($file == null) $file = dirname(__FILE__) . '/../../logs/viewer-debug.log'; if (self::$debugViewer) { file_put_contents($file, $message.$delimiter, FILE_APPEND); } } /** * Constructor - Sets the templateDir and compileDir for the Smarty files * @param <String> - $media Layout/Media name */ function __construct($media='') { parent::__construct(); $THISDIR = dirname(__FILE__); $templatesDir = ''; $compileDir = ''; if(!empty($media)) { self::$currentLayout = $media; $templatesDir = $THISDIR . '/../../layouts/'.$media; $compileDir = $THISDIR . '/../../test/templates_c/'.$media; } global $default_layout; $checkforlayout = file_exists($THISDIR . '/../../layouts/'.$default_layout) ; if($default_layout && $checkforlayout ) { self::$currentLayout = $default_layout; $templatesDir = $THISDIR . '/../../layouts/'.$default_layout; $compileDir = $THISDIR . '/../../test/templates_c/'.$default_layout; } else if(empty($templatesDir) || !file_exists($templatesDir)) { self::$currentLayout = self::getDefaultLayoutName(); $templatesDir = $THISDIR . '/../../layouts/'.self::getDefaultLayoutName(); $compileDir = $THISDIR . '/../../test/templates_c/'.self::getDefaultLayoutName(); } if (!file_exists($compileDir)) { mkdir($compileDir, 0777, true); } $this->setTemplateDir(array($templatesDir)); $this->setCompileDir($compileDir); // FOR SECURITY // Escape all {$variable} to overcome XSS // We need to use {$variable nofilter} to overcome double escaping // TODO: Until we review the use disabled. //$this->registerFilter('variable', array($this, 'safeHtmlFilter')); // FOR DEBUGGING: We need to have this only once. static $debugViewerURI = false; if (self::$debugViewer && $debugViewerURI === false) { $debugViewerURI = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); if (!empty($_POST)) { $debugViewerURI .= '?' . http_build_query($_POST); } else { $debugViewerURI = $_SERVER['REQUEST_URI']; } $this->log("URI: $debugViewerURI, TYPE: " . $_SERVER['REQUEST_METHOD']); } } function safeHtmlFilter($content, $smarty) { //return htmlspecialchars($content,ENT_QUOTES,UTF-8); // NOTE: to_html is being used as data-extraction depends on this // We shall improve this as it plays role across the product. return to_html($content); } /** * Function to get the current layout name * @return <String> - Current layout name if not empty, otherwise Default layout name */ public static function getLayoutName() { if(!empty(self::$currentLayout)) { return self::$currentLayout; } return self::getDefaultLayoutName(); } /** * Function to return for default layout name * @return <String> - Default Layout Name */ public static function getDefaultLayoutName(){ return self::DEFAULTLAYOUT; } /** * Function to get the module specific template path for a given template * @param <String> $templateName * @param <String> $moduleName * @return <String> - Module specific template path if exists, otherwise default template path for the given template name */ public function getTemplatePath($templateName, $moduleName='') { $moduleName = str_replace(':', '/', $moduleName); $completeFilePath = $this->getTemplateDir(0). DIRECTORY_SEPARATOR . "modules/$moduleName/$templateName"; if(!empty($moduleName) && file_exists($completeFilePath)) { return "modules/$moduleName/$templateName"; } else { // Fall back lookup on actual module, in case where parent module doesn't contain actual module within in (directory structure) if(strpos($moduleName, '/') > 0) { $moduleHierarchyParts = explode('/', $moduleName); $actualModuleName = $moduleHierarchyParts[count($moduleHierarchyParts)-1]; $baseModuleName = $moduleHierarchyParts[0]; $fallBackOrder = array ( "$actualModuleName", "$baseModuleName/Sphere" ); foreach($fallBackOrder as $fallBackModuleName) { $intermediateFallBackFileName = 'modules/'. $fallBackModuleName .'/'.$templateName; $intermediateFallBackFilePath = $this->getTemplateDir(0). DIRECTORY_SEPARATOR . $intermediateFallBackFileName; if(file_exists($intermediateFallBackFilePath)) { return $intermediateFallBackFileName; } } } return "modules/Sphere/$templateName"; } } /** * Function to display/fetch the smarty file contents * @param <String> $templateName * @param <String> $moduleName * @param <Boolean> $fetch * @return html data */ public function view($templateName, $moduleName='', $fetch=false) { $templatePath = $this->getTemplatePath($templateName, $moduleName); $templateFound = $this->templateExists($templatePath); // Logging if (self::$debugViewer) { $templatePathToLog = $templatePath; $qualifiedModuleName = str_replace(':', '/', $moduleName); // In case we found a fallback template, log both lookup and target template resolved to. if (!empty($moduleName) && strpos($templatePath, "modules/$qualifiedModuleName/") !== 0) { $templatePathToLog = "modules/$qualifiedModuleName/$templateName > $templatePath"; } $this->log("VIEW: $templatePathToLog, FOUND: " . ($templateFound? "1" : "0")); foreach ($this->tpl_vars as $key => $smarty_variable) { // Determine type of value being pased. $valueType = 'literal'; if (is_object($smarty_variable->value)) $valueType = get_class($smarty_variable->value); else if (is_array($smarty_variable->value)) $valueType = 'array'; $this->log(sprintf("DATA: %s, TYPE: %s", $key, $valueType)); } } // END if ($templateFound) { if($fetch) { return $this->fetch($templatePath); } else { $this->display($templatePath); } return true; } return false; } /** * Static function to get the Instance of the Class Object * @param <String> $media Layout/Media * @return Sphere_Viewer instance */ static function getInstance($media='') { $instance = new self($media); return $instance; } } function vtemplate_path($templateName, $moduleName='') { $viewerInstance = Sphere_Viewer::getInstance(); $args = func_get_args(); return call_user_func_array(array($viewerInstance, 'getTemplatePath'), $args); } /** * Generated cache friendly resource URL linked with version of Sphere */ function vresource_url($url) { global $vtiger_current_version; if (stripos($url, '://') === false) { $url = $url .'?v='.$vtiger_current_version; } return $url; } function getPurifiedSmartyParameters($param){ return htmlentities($_REQUEST[$param]); }