diff --git a/framework/api/entry.class.php b/framework/api/entry.class.php index 2e385865b0..da2ad70556 100644 --- a/framework/api/entry.class.php +++ b/framework/api/entry.class.php @@ -444,6 +444,12 @@ class baseEntry $this->setPost($field, $value); } + + /* Use htmlspecialcharts for rich text fields. */ + foreach($fields as $field) + { + if(in_array($field, array('desc', 'spec', 'verify', 'steps')) and isset($_POST[$field])) $_POST[$field] = htmlspecialchars($_POST[$field]); + } } /** diff --git a/framework/base/control.class.php b/framework/base/control.class.php index b5892ef58c..cf18d4a5f1 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -320,6 +320,7 @@ class baseControl $this->{$moduleName} = $model; $this->dao = $model->dao; + $this->cache = $model->cache; return $model; } diff --git a/framework/base/model.class.php b/framework/base/model.class.php index bae979b5a6..9dec80362c 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -151,6 +151,7 @@ class baseModel $this->loadDAO(); $this->setSuperVars(); + $this->loadCache(); /** * 读取当前模块的tao类。 @@ -324,6 +325,20 @@ class baseModel $this->dao = $dao; } + /** + * 加载缓存类。 + * Load cache class. + * + * @access public + * @return void + */ + public function loadCache() + { + $this->app->loadClass('cache', $static = true); + $namespace = isset($this->session->user->account) ? $this->session->user->account : 'guest'; + $this->cache = cache::create($this->config->cache->driver, $namespace, $this->config->cache->lifetime); + } + /** * 删除记录。 * Delete one record. diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 9958027df1..051eb9226a 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -2405,6 +2405,43 @@ class baseRouter return $module; } + /** + * 输出内容。 + * Output the content. + * + * @return string + */ + public function outputPage() + { + $cacheEnable = $this->config->cache->enableFullPage; + /* If caching is not turned on, pages that do not need to be cached, or when searching, they are not cached. */ + if(!$cacheEnable || !in_array("{$this->moduleName}|{$this->methodName}", $this->config->cache->fullPages) || stripos($this->server->request_uri, 'search') !== false || isset($_GET['_nocache']) || $this->server->http_x_zt_refresh) + { + $this->loadModule(); + return helper::removeUTF8Bom(ob_get_clean()); + } + + $this->loadClass('cache', $static = true); + $cacheKey = md5($this->server->request_uri); + $namespace = isset($this->session->user->account) ? $this->session->user->account : 'guest'; + $cache = cache::create($this->config->cache->fullPageDriver, $namespace, $this->config->cache->fullPageLifetime); + + if($cache->has($cacheKey)) + { + if(!headers_sent()) header('X-Zt-Hit-Cache: 1'); + $content = $cache->get($cacheKey); + } + else + { + ob_start(); + $result = $this->loadModule(); + $content = helper::removeUTF8Bom(ob_get_clean()); + /* If the module is loaded successfully, cache the content. */ + if($result !== false) $cache->set($cacheKey, $content); + } + return $content; + } + /** * 加载指定模块下的某种对象。 * Load the target object of one module. diff --git a/framework/control.class.php b/framework/control.class.php index a9956d67a8..8c3ef500e8 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -121,7 +121,7 @@ class control extends baseControl */ public function setDefaultPrivByWorkflow() { - $actionList = $this->dao->select('module, action')->from(TABLE_WORKFLOWACTION) + $actionList = $this->dao->select('module, `action`')->from(TABLE_WORKFLOWACTION) ->where('createdBy')->eq($this->app->user->account) ->andWhere('buildin')->eq('0') ->fetchGroup('module'); diff --git a/framework/helper.class.php b/framework/helper.class.php index 9a6b3cd579..091465b628 100644 --- a/framework/helper.class.php +++ b/framework/helper.class.php @@ -392,12 +392,28 @@ class helper extends baseHelper } /** + * 是否是内网。 + * Check is intranet. + * * @return bool */ public static function isIntranet() { return !defined('USE_INTRANET') ? false : USE_INTRANET; } + + /** + * 检查是否启用缓存。 + * Check is enable cache. + * + * @return bool + */ + public static function isCacheEnabled() + { + if(isset($_GET['_nocache']) || isset($_SERVER['HTTP_X_ZT_REFRESH'])) return false; + global $config; + return $config->cache->enable; + } } /** diff --git a/framework/model.class.php b/framework/model.class.php index f1fc04fa1a..50591d011e 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -129,7 +129,6 @@ class model extends baseModel * @access public * @return string */ - public function buildMenu($moduleName, $methodName, $params, $data, $type = 'view', $icon = '', $target = '', $class = '', $onlyBody = false, $misc = '' , $title = '', $returnHtml = true) { if(str_contains($moduleName, '.')) [$appName, $moduleName] = explode('.', $moduleName); diff --git a/lib/base/front/front.class.php b/lib/base/front/front.class.php index e8f8cf2fd0..ae59ad0497 100644 --- a/lib/base/front/front.class.php +++ b/lib/base/front/front.class.php @@ -1303,7 +1303,7 @@ EOT; * Set js value. * * @param string $key - * @param mix $value + * @param mixed $value * @static * @access public * @return string diff --git a/lib/dbh/dbh.class.php b/lib/dbh/dbh.class.php index 21138efbc0..c7e601d49e 100644 --- a/lib/dbh/dbh.class.php +++ b/lib/dbh/dbh.class.php @@ -265,6 +265,7 @@ class dbh */ public function tableExits($tableName) { + $tableName = str_replace('`', "'", $tableName); $tableName = str_replace("'", "", $tableName); $sql = "SHOW TABLES FROM {$this->config->name} like '{$tableName}'"; switch($this->config->driver) @@ -273,7 +274,7 @@ class dbh $sql = "SHOW TABLES FROM {$this->config->name} like '{$tableName}'"; break; case 'dm': - $sql = "SELECT * FROM all_tables WHERE owner='{$this->config->name}' AND table_name={$tableName}"; + $sql = "SELECT * FROM all_tables WHERE owner='{$this->config->name}' AND table_name='{$tableName}'"; break; default: $sql = ''; @@ -372,8 +373,11 @@ class dbh */ public function formatDmSQL($sql) { - $sql = trim($sql); - $sql = str_replace(array('\r', '\n'), ' ', $sql); + $sql = trim($sql); + /* '\\\\n' try to compatible screen json like \u0232\\nBug. */ + $sql = str_replace(array('\\\\n', '\r', '\n'), ' ', $sql); + $sql = $this->formatFunction($sql); + $actionPos = strpos($sql, ' '); $action = strtoupper(substr($sql, 0, $actionPos)); $setPos = 0; @@ -394,7 +398,7 @@ class dbh if(strpos($sql, '\\\\') !== FALSE) $sql = str_replace('\\\\', '\\', $sql); break; case 'CREATE': - if(stripos($sql, 'CREATE VIEW') === 0) return ''; + if(stripos($sql, 'CREATE VIEW') === 0) $sql = str_replace('CREATE VIEW', 'CREATE OR REPLACE VIEW', $sql); if(stripos($sql, 'CREATE FUNCTION') === 0) return ''; if(stripos($sql, 'CREATE OR REPLACE VIEW ') === 0) @@ -423,10 +427,11 @@ class dbh $sql = substr($sql, 0, $fieldsBegin+6) . $fields . substr($sql, $fieldsEnd); return str_replace('CREATE OR REPLACE VIEW ', 'CREATE VIEW ', $sql); } - elseif(stripos($sql, 'CREATE UNIQUE INDEX') === 0) + elseif(stripos($sql, 'CREATE UNIQUE INDEX') === 0 || stripos($sql, 'CREATE INDEX') === 0) { preg_match('/ON\ +[0-9a-zA-Z\_\.]+\`([0-9a-zA-Z\_]+)\`/', $sql, $matches); - $tableName = explode('_', $matches[1]); + + $tableName = str_replace($this->config->prefix, '', $matches); $sql = preg_replace('/INDEX\ +\`/', 'INDEX `' . strtolower($tableName[1]) . '_', $sql); } case 'ALTER': @@ -437,6 +442,9 @@ class dbh if(stripos($sql, 'SET SCHEMA') === 0) return $sql; case 'USE': return ''; + case 'DESC'; + $tableName = str_replace('DESC ', '', $sql); + return "select COLUMN_NAME as Field from all_tab_columns where Table_Name='$tableName'"; case 'DROP': return $this->formatField($sql); } @@ -480,6 +488,28 @@ class dbh } } + /** + * Format function. + * + * @param string $sql + * @access public + * @return string + */ + public function formatFunction($sql) + { + switch($this->config->driver) + { + case 'dm': + /* DATE convert to TO_CHAR. */ + $sql = preg_replace("/\bDATE\(([^)]*)\)/", "TO_CHAR($1, 'yyyy-mm-dd')", $sql, -1); + + return $sql; + + default: + return $sql; + } + } + /** * Format if function of dmdb. * @@ -554,11 +584,47 @@ class dbh { foreach($datetimeMatch[0] as $match) $sql = str_replace($match, $match . '(0)', $sql); } + + if(strpos($sql, "ALTER TABLE") !== false) $sql = $this->convertAlterTableSql($sql); } return $sql; } + /** + * Convert alter table sql. + * + * @param mixed $sql + * @access public + * @return void + */ + public function convertAlterTableSql($sql) + { + /* If table has datas and sql no default values defined, add default ''/0. */ + if(strpos($sql, "NOT NULL") !== false && strpos($sql, "DEFAULT") === false) + { + $default = ''; + if(strpos($sql, "integer") !== false) $default = 0; + $sql = str_replace("NOT NULL", "NOT NULL DEFAULT '" . $default ."'", $sql); + } + + $pattern = '/ALTER TABLE "(.*?)" CHANGE "(.*?)" "(.*?)" (.*?)(?:;|$)/'; + preg_match($pattern, $sql, $matches); + if(count($matches) != 5) return $sql; + + $tableName = $matches[1]; + $oldColumnName = $matches[2]; + $newColumnName = $matches[3]; + $params = str_replace("'", "''", $matches[4]); + + $sql = 'begin '; + if($oldColumnName != $newColumnName) $sql .= "execute immediate 'ALTER TABLE $tableName ALTER " . '"' . $oldColumnName . '" RENAME TO "' . $newColumnName . '"' . "';"; + $sql .= "execute immediate 'ALTER TABLE $tableName MODIFY " . '"' . $newColumnName . '" ' . $params . "';"; + $sql .= 'end;'; + + return $sql; + } + /** * Quote. *