Initial project files: BESCMS full source

This commit is contained in:
bes
2026-08-13 23:37:46 +08:00
parent fa6cddb540
commit 2e26f85723
2166 changed files with 396625 additions and 0 deletions
+558
View File
@@ -0,0 +1,558 @@
<?php namespace Phpcmf\Library;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件,可以通过继承类方法来重写此文件
**/
// 表单验证类
class Form {
public $fields;
public $mfields;
protected $id = 0;
// 初始化
public function id($id) {
$this->id = (int)$id;
return $this;
}
// 获取表单临时存储数据
public function auto_form_data($name, $data) {
// 默认数据
$dt = \Phpcmf\Service::L('cache')->init('file')->get(md5($name));
if (!$dt) {
return $data;
}
$dt['is_form_cache'] = 1;
return $data ? $dt + $data : $dt;
}
// 删除表单临时存储数据
public function auto_form_data_delete($name) {
\Phpcmf\Service::L('cache')->init('file')->delete(md5($name));
}
/**
* 自动临时存储表单数据ajax
*/
public function auto_form_data_ajax($name) {
return '
$(function(){
setInterval("auto_form_data_ajax()", 5000);
});
function auto_form_data_ajax() {
$.ajax({
type: "POST",
url: "'.dr_web_prefix('index.php?s=api&c=api&m=save_form_data&name='.$name).'",
dataType: "json",
data: $("#myform").serialize(),
success: function(data){ }
});
}
function auto_form_data_delete() {
var index = layer.load(2, {
shade: [0.3,\'#fff\'],
time: 10000
});
$.ajax({
type: "GET",
url: "'.dr_web_prefix('index.php?s=api&c=api&m=delete_form_data&name='.$name).'",
dataType: "json",
success: function(json){
layer.close(index);
dr_tips(json.code, json.msg);
setTimeout("window.location.reload(true)", 3000)
}
});
}
';
}
/**
*
* 验证字段格式
* 字段名 => [name显示名称, rule验证规则(支持正则), length长度]
* field 自定义字段配置
* id 是否修改的条件
**/
public function validation($data, $config, $fields = [], $old = []) {
if (!$data) {
$data = [];
}
// 初始化信息
\Phpcmf\Service::L('Field')->old = $old;
\Phpcmf\Service::L('Field')->data = [];
$attach = []; // 附件信息
// 表单规则验证
if ($config) {
foreach ($config as $name => $t) {
// 长度验证
if ($t['length'] && dr_strlen($data[$name]) > $t['length']) {
return [[], ['name' => $name, 'error' => dr_lang('长度不规范')]];
}
// 规则验证
if ($t['rule']) {
foreach ($t['rule'] as $rule => $error) {
switch ($rule) {
case 'empty':
if (!$data[$name] && !dr_strlen($data[$name])) {
return [[], ['name' => $name, 'error' => $error]];
}
break;
case 'table':
if (!(preg_match('/^[a-z]+[0-9]+/i', (string)$data[$name]) || preg_match('/[a-z]+/i', (string)$data[$name]))) {
return [[], ['name' => $name, 'error' => $error]];
}
break;
case 'pinyin':
if (!preg_match('/[a-z0-9]+/i', (string)$data[$name])) {
return [[], ['name' => $name, 'error' => $error]];
}
break;
}
}
}
// 过滤
if ($t['filter']) {
foreach ($t['filter'] as $value) {
switch ($value) {
case 'intval':
$data[$name] = intval($data[$name]);
break;
}
}
}
}
}
$notfields = [];
$radio_link_required = [];
// 自定义字段验证
if ($fields) {
$post = [];
$this->fields = $fields;
// 格式化字段值
foreach ($fields as $fid => $field) {
// 验证字段对象的有效性
$obj = \Phpcmf\Service::L('Field')->get($field['fieldtype']);
if (!$obj) {
unset($fields[$fid]);
continue; // 对象不存在
}
$obj->init($field);
$name = $field['fieldname']; // 字段名称
$obj->id = $this->id;
// 非后台时
if (!IS_ADMIN) {
if (!$field['ismember']) {
$notfields[] = $field['fieldname']; // 无权限排除的字段
unset($fields[$fid]);
continue; // 前端字段筛选
} elseif ($obj->_not_edit($field, $old[$field['fieldname']])) {
unset($fields[$fid]);
$notfields[] = $field['fieldname']; // 无权限排除的字段
continue; // 前端禁止修改时
} elseif ($field['setting']['show_member'] && dr_array_intersect(\Phpcmf\Service::C()->member['groupid'], $field['setting']['show_member'])) {
unset($fields[$fid]);
$notfields[] = $field['fieldname']; // 无权限排除的字段
continue; // 非后台时 判断用户权限
}
} elseif (IS_ADMIN && $field['setting']['show_admin'] && !dr_in_array(1, \Phpcmf\Service::C()->admin['roleid'])
&& dr_array_intersect(\Phpcmf\Service::C()->admin['roleid'], $field['setting']['show_admin'])) {
$notfields[] = $field['fieldname']; // 无权限排除的字段
continue; // 后台时 判断管理员权限
}
// 验证字段
$validate = $field['setting']['validate']; // 字段验证规则
// 默认xss开关
$xss = 0;
if ($obj->close_xss) {
$xss = 0;
} elseif ($obj->use_xss) {
$xss = 1;
} elseif (isset($validate['xss']) && $validate['xss']) {
// 手动开启xss
$xss = 1;
}
// 从表单获取值
$post[$name] = $value = ($xss ? \Phpcmf\Service::L('Security')->xss_clean($data[$name]) : $data[$name]);
// 验证字段值
$frt = $obj->check_value($field, $value);
if ($frt) {
return [[], ['name' => $name, 'error' => $frt]];
}
// Radio联动字段
if ($field['fieldtype'] == 'Radio'
&& isset($field['setting']['option']['is_field_ld']) && $field['setting']['option']['is_field_ld']
&& isset($field['setting']['option']['field_ld'][$value])
&& isset($field['setting']['option']['field_ld'][$value]['hide'])
) {
$radio_link_required = dr_array2array($field['setting']['option']['field_ld'][$value]['hide'], $radio_link_required);
}
// 验证必填字段
if ($obj->is_validate && $validate['required'] && !dr_in_array($name, $radio_link_required)) {
if (IS_ADMIN && dr_in_array(1, \Phpcmf\Service::C()->admin['roleid'])) {
// 后台超管不验证必填
} else {
// 开始验证必填字段
$frt = $obj->check_required($field, $value);
if ($frt) {
return [[], ['name' => $name, 'error' => $frt]];
}
}
// 正则验证
if (!is_array($value) && $validate['pattern'] && !preg_match($validate['pattern'], $value)) {
return [[], ['name' => $name, 'error' => $field['name'].''.($validate['errortips'] ? dr_lang($validate['errortips']) : dr_lang('格式不正确'))]];
}
}
// 编辑器长度判断(依据 php.ini 的 post_max_size,预留附件与其它字段空间)
if (stripos($field['fieldtype'], 'editor') !== false && dr_strlen($data[$name]) > dr_form_editor_max_length()) {
return [[], ['name' => $name, 'error' => dr_lang('%s长度超限', $field['name'])]];
}
// 函数/方法校验
if ($validate['check']) {
if (strpos($validate['check'], '_') === 0) {
// 方法格式
$method = substr($validate['check'], 1);
if (method_exists($this, $method)) {
if ('check_member' == $method && $value == 'guest') {
// 游客不验证
} else {
$rt = call_user_func_array([$this, $method], [$value, $data, $old]);
if (!$rt['code']) {
return [[], ['name' => $name, 'error' => $rt['msg']]];
}
}
} else {
log_message('error', "校验方法 $method 不可用");
}
} else {
// 函数格式
$func = $validate['check'];
if (dr_is_call_function($func)) {
$rt = call_user_func_array($func, [$value, $data, $old]);
if (!$rt['code']) {
return [[], ['name' => $name, 'error' => $rt['msg']]];
}
} else {
log_message('error', "校验函数 $func 不可用");
}
}
}
// 过滤函数/方法
if ($validate['filter']) {
if (strpos($validate['filter'], '_') === 0) {
// 方法格式
$method = substr($validate['filter'], 1);
if (method_exists($this, $method)) {
// 开始过滤
$post[$name] = call_user_func_array([$this, $method], [$value, $data, $old]);
} else {
log_message('error', "过滤方法 $method 不可用");
}
} else {
// 函数格式
$func = $validate['filter'];
if (dr_is_call_function($func)) {
// 开始过滤
$post[$name] = call_user_func_array($func, [$value, $data, $old]);
} else {
log_message('error', "过滤函数 $func 不可用");
}
}
}
// 判断表字段值的唯一性
if ($field['ismain'] && $field['setting']['option']['unique']) {
if (empty(dr_strlen($post[$name]))) {
return [[], ['name' => $name, 'error' => dr_lang('%s不能为空', $field['name'])]];
}
if (\Phpcmf\Service::C()->init['table']) {
$table = \Phpcmf\Service::M()->dbprefix(\Phpcmf\Service::C()->init['table']);
if (\Phpcmf\Service::M()->db->fieldExists($name, $table)) {
$rt = \Phpcmf\Service::M()->db->table(\Phpcmf\Service::C()->init['table'])->where('id<>'. $this->id)->where($name, $post[$name])->countAllResults();
if ($rt) {
return [[], ['name' => $name, 'error' => dr_lang('%s已经存在', $field['name'])]];
}
} else {
log_message('error', "字段唯一性验证失败:表".$table."中字段".$name."不存在!");
}
} else {
log_message('error', "字段唯一性验证失败:数据表不存在!");
}
}
}
// 存储附件id
$attach['add'] = $attach['del'] = [];
// 主表附表归类
foreach ($fields as $field) {
// 验证字段对象的有效性
$obj = \Phpcmf\Service::L('Field')->get($field['fieldtype'], $this->id, $post);
if (!$obj) {
continue; // 对象不存在
}
$obj->insert_value($field); // 格式化入库值
// 处理附件归档
if (SYS_ATTACHMENT_DB) {
// 通过附件处理方法获得增加和删除的附件
list($add_id, $del_id) = $obj->attach(
\Phpcmf\Service::L('Field')->data[$field['ismain']][$field['fieldname']],
$old[$field['fieldname']]
);
$attach['add'] = $add_id ? dr_array2array($add_id, $attach['add']) : $attach['add'];
$attach['del'] = $del_id ? dr_array2array($del_id, $attach['del']) : $attach['del'];
}
}
// 格式化后的数据
$data = \Phpcmf\Service::L('Field')->data;
// 获取uid
}
return [$data, [], $attach, $notfields];
}
// 获取已发短信验证码
public function get_mobile_code($phone) {
return \Phpcmf\Service::L('cache')->get_auth_data('phone-code-'.$phone, SITE_ID, defined('SYS_CACHE_SMS') && SYS_CACHE_SMS ? SYS_CACHE_SMS : 300);
}
// 储存已发短信验证码
public function set_mobile_code($phone, $code) {
return \Phpcmf\Service::L('cache')->set_auth_data('phone-code-'.$phone, $code, SITE_ID);
}
// 验证码类
public function check_captcha($id) {
// API请求时,是否进行验证图片
if (IS_API_HTTP && defined('SYS_API_CODE') && !SYS_API_CODE) {
return true;
}
if (!IS_ADMIN && function_exists('my_check_captcha')) {
return my_check_captcha($id);
}
$data = trim((string)\Phpcmf\Service::L('input')->post($id));
if (!$data) {
IS_DEV && log_message('debug', '图片验证码验证失败:没有输入验证码'.dr_safe_replace(\Phpcmf\Service::L('input')->ip_address().':'.\Phpcmf\Service::L('input')->get_user_agent()));
return false;
}
$code = \Phpcmf\Service::L('cache')->get_auth_data('web-captcha-'.USER_HTTP_CODE, SITE_ID, 300);
if (!$code) {
IS_DEV && log_message('error', '图片验证码未生成('.USER_HTTP_CODE.''.dr_safe_replace(\Phpcmf\Service::L('input')->ip_address().':'.\Phpcmf\Service::L('input')->get_user_agent()));
return false;
} elseif (strtolower($data) == strtolower($code)) {
\Phpcmf\Service::L('cache')->del_auth_data('web-captcha-'.USER_HTTP_CODE, SITE_ID);
return true;
}
IS_DEV && log_message('debug', '图片验证码验证失败:你输入的是('.$data.'),正确的是('.$code.''.dr_safe_replace(\Phpcmf\Service::L('input')->ip_address().':'.\Phpcmf\Service::L('input')->get_user_agent()));
return false;
}
// 验证码类:只比较不删除
public function check_captcha_value($data) {
// API请求时,是否进行验证图片
if (IS_API_HTTP && defined('SYS_API_CODE') && !SYS_API_CODE) {
return true;
} elseif (!$data) {
IS_DEV && log_message('debug', '图片验证码验证失败:没有输入验证码');
return false;
}
$data = trim((string)$data);
if (!IS_ADMIN && function_exists('my_check_captcha_value')) {
return my_check_captcha_value($data);
}
$code = \Phpcmf\Service::L('cache')->get_auth_data('web-captcha-'.USER_HTTP_CODE, SITE_ID, 300);
if (!$code) {
IS_DEV && log_message('error', '图片验证码未生成('.USER_HTTP_CODE.''.dr_safe_replace(\Phpcmf\Service::L('input')->ip_address().':'.\Phpcmf\Service::L('input')->get_user_agent()));
return false;
} elseif (strtolower($data) == strtolower($code)) {
\Phpcmf\Service::L('cache')->del_auth_data('web-captcha-'.USER_HTTP_CODE, SITE_ID);
return true;
}
IS_DEV && log_message('debug', '图片验证码验证失败:你输入的是('.$data.'),正确的是('.$code.''.dr_safe_replace(\Phpcmf\Service::L('input')->ip_address().':'.\Phpcmf\Service::L('input')->get_user_agent()));
return false;
}
// 验证手机号码长度
public function check_phone($value) {
if (!$value) {
return false;
} elseif (dr_strlen($value) > 30) {
return false;
}
return true;
}
// 验证邮件地址
public function check_email($value) {
if (!$value) {
return false;
} elseif (!preg_match('/^[\w\-\.]+@[\w\-\.]+(\.\w+)+$/', $value)) {
return false;
} elseif (strpos($value, '"') !== false || strpos($value, '\'') !== false) {
return false;
}
return true;
}
// 验证账号
public function check_username($value) {
if (!$value) {
return dr_return_data(0, dr_lang('账号不能为空'), ['field' => 'username']);
} elseif (\Phpcmf\Service::C()->member_cache['register']['preg']
&& !preg_match(\Phpcmf\Service::C()->member_cache['register']['preg'], $value)) {
// 验证账号的组成格式
return dr_return_data(0, dr_lang('账号格式不正确'), ['field' => 'username']);
} elseif (strpos($value, '"') !== false
|| strpos($value, '<') !== false
|| strpos($value, '>') !== false
|| strpos($value, '\'') !== false
) {
// 引号判断
return dr_return_data(0, dr_lang('账号名存在非法字符'), ['field' => 'username']);
} elseif (\Phpcmf\Service::C()->member_cache['config']['userlen']
&& mb_strlen($value) < \Phpcmf\Service::C()->member_cache['config']['userlen']) {
// 验证账号长度
return dr_return_data(0, dr_lang('账号长度不能小于%s位,当前%s位', \Phpcmf\Service::C()->member_cache['config']['userlen'], mb_strlen($value)), ['field' => 'username']);
} elseif (\Phpcmf\Service::C()->member_cache['config']['userlenmax']
&& mb_strlen($value) > \Phpcmf\Service::C()->member_cache['config']['userlenmax']) {
// 验证账号长度
return dr_return_data(0, dr_lang('账号长度不能大于%s位,当前%s位', \Phpcmf\Service::C()->member_cache['config']['userlenmax'], mb_strlen($value)), ['field' => 'username']);
}
$notallow = \Phpcmf\Service::C()->member_cache['register']['notallow'];
if (!$notallow || !is_array($notallow)) {
$notallow = [];
}
$notallow[] = dr_lang('游客');
// 后台不允许注册的词语,放在最后一次比较
foreach ($notallow as $a) {
if (dr_strlen($a) && strpos($value, $a) !== false) {
return dr_return_data(0, dr_lang('账号名不允许注册'), ['field' => 'username']);
}
}
return dr_return_data(1, 'ok');
}
// 验证账号的密码
public function check_password($value, $username) {
if (!$value) {
return dr_return_data(0, dr_lang('密码不能为空'), ['field' => 'password']);
} elseif (!\Phpcmf\Service::C()->member_cache['config']['user2pwd'] && $value == $username) {
return dr_return_data(0, dr_lang('密码不能与账号相同'), ['field' => 'password']);
} elseif (\Phpcmf\Service::C()->member_cache['config']['pwdpreg']
&& !preg_match(trim(\Phpcmf\Service::C()->member_cache['config']['pwdpreg']), $value)) {
return dr_return_data(0, dr_lang('密码格式不正确'), ['field' => 'password']);
} elseif (\Phpcmf\Service::C()->member_cache['config']['pwdlen']
&& mb_strlen($value) < \Phpcmf\Service::C()->member_cache['config']['pwdlen']) {
return dr_return_data(0, dr_lang('密码长度不能小于%s位,当前%s位', \Phpcmf\Service::C()->member_cache['config']['pwdlen'], mb_strlen($value)), ['field' => 'password']);
} elseif (mb_strlen($value) > 100) {
return dr_return_data(0, dr_lang('密码长度不能过长'), ['field' => 'password']);
}
return dr_return_data(1, 'ok');
}
// 验证姓名
public function check_name($value) {
if (!$value) {
return false;
} elseif (\Phpcmf\Service::C()->member_cache['register']['cutname'] && mb_strlen($value) > \Phpcmf\Service::C()->member_cache['register']['cutname']) {
return false;
}
return true;
}
// 验证域名
public function check_domain($value) {
if (!$value) {
return false;
}
foreach (['/', '?', '&', '\\', '*', ' ', '..', '(', ')', '\'', '"', ',', ';'] as $p) {
if (strpos($value, $p) !== false) {
return false;
}
}
return true;
}
// 验证目录式域名
public function check_domain_dir($value) {
if (!$value) {
return false;
}
foreach (['/', '?', '&', '\\', '*', ' ', '..', '(', ')', '\'', '"', ',', ';'] as $p) {
if (strpos($value, $p) !== false) {
return false;
}
}
if (substr_count($value, '/') > 1) {
return false;
}
return true;
}
// 生成随机验证码
public function get_rand_value() {
return rand(100000, 999999);
}
//=====校验方法=========
/**
* 验证会员名称是否存在
*
* @param $value 当前字段提交的值
* @return flase不通过 , true通过
*/
public function check_member($value) {
if (!$value || dr_lang('游客') == $value) {
return dr_return_data(1);
} elseif (!\Phpcmf\Service::M('member')->uid($value)) {
return dr_return_data(0, dr_lang('账号【%s】不存在', $value));
}
return dr_return_data(1);
}
}