PHPIndex

This page lists files in the current directory. You can view content, get download/execute commands for Wget, Curl, or PowerShell, or filter the list using wildcards (e.g., `*.sh`).

app.class.php
wget 'https://sme10.lists2.roe3.org/kodbox/plugins/msgWarning/controller/msg/app.class.php'
View Content
<?php 
/**
 * 通知事件——应用服务类
 */
class msgWarningMsgApp extends Controller {
	public function __construct() {
		parent::__construct();
		$this->pluginName = 'msgWarningPlugin';
    }

	public function index($evntInfo) {
		return array();
	}

}
coll.class.php
wget 'https://sme10.lists2.roe3.org/kodbox/plugins/msgWarning/controller/msg/coll.class.php'
View Content
<?php 
/**
 * 通知事件——协同办公类
 */
class msgWarningMsgColl extends Controller {
	public function __construct() {
		parent::__construct();
		$this->pluginName = 'msgWarningPlugin';
    }

	public function index($evntInfo) {
		return array();
	}

}
data.class.php
wget 'https://sme10.lists2.roe3.org/kodbox/plugins/msgWarning/controller/msg/data.class.php'
View Content
<?php 
/**
 * 通知事件——数据资产类
 */
class msgWarningMsgData extends Controller {
	public function __construct() {
		parent::__construct();
		$this->pluginName = 'msgWarningPlugin';
    }

	public function index($evntInfo) {
		$data = array();
		switch ($evntInfo['event']) {
			case 'dataFileDownErr':
				$data = $this->dataFileDownErr($evntInfo);
				break;
			default:
				# code...
				break;
		}
		return $data;
	}


	/**
	 * 文件下载异常提醒
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function dataFileDownErr($evntInfo) {
		// 触发条件
		$policy = $evntInfo['policy'];
		if (!$policy) return array();
		$cntMax = intval(_get($policy, 'cntMax', 0));
		if (!$cntMax) return array();

		// 超限的用户id列表缓存
		$cckey = $this->pluginName.'.dataFileDownErr.'.date('Ymd');
		$cache = Cache::get($cckey);
		$users = $cache ? explode(',', $cache) : array();

		// 统计用户下载文件次数
		$timeFrom 	= strtotime(date('Y-m-d')); 
		$timeTo 	= time();
		$where = array(
			'createTime'=> array('between', array($timeFrom, $timeTo)),
			'type'		=> array('in', array('explorer.index.fileOut', 'explorer.index.fileDownload',)),
		);
		if ($users) $where['userID'] = array('not in', $users);
		$fields = array('userID', 'count(*)' => 'cnt');
		$list = Model('SystemLog')->where($where)->group('userID')->field($fields)->select();
		$data = array();
		foreach ($list as $item) {
		    $cnt = intval($item['cnt']);
			if (!$cnt || $cnt < $cntMax) continue;
			$data[] = $item['userID'];
		}
		$users = array_unique(array_merge($users, $data));
		if (!$users) return array();
		Cache::set($cckey, implode(',', $users));

		// 获取用户名单
		$list = Model('User')->where(array('userID' => array('in', $users)))->field('userID, name, nickName')->select();
		$user = array();
		foreach ($list as $item) {
		    $user[] = $item['nickName'] ? $item['nickName'] : $item['name'];
		}

		// 前端提醒只显示基础消息(第1条),后端消息展示全部
		$msg = sprintf(LNG('msgWarning.data.downFileErr'), date('Y-m-d H:i'), count($users), $cntMax);
		return array($msg, implode(',', $user));
	}

}
dev.class.php
wget 'https://sme10.lists2.roe3.org/kodbox/plugins/msgWarning/controller/msg/dev.class.php'
View Content
<?php 
/**
 * 通知事件——硬件资源类
 */
class msgWarningMsgDev extends Controller {
	public function __construct() {
		parent::__construct();
		$this->pluginName = 'msgWarningPlugin';
    }

	public function index($evntInfo) {
		return array();
	}


}
index.class.php
wget 'https://sme10.lists2.roe3.org/kodbox/plugins/msgWarning/controller/msg/index.class.php'
View Content
<?php 
/**
 * 发送通知
 */
class msgWarningMsgIndex extends Controller {
	public function __construct() {
		parent::__construct();
		$this->pluginName = 'msgWarningPlugin';
    }

	/**
	 * 发送消息
	 * @param [type] $msg
	 * @param [type] $target	userid[,,,]
	 * @return void
	 */
	public function send($msg, $target) {
		$config = Action($this->pluginName)->getConfig();
		$typeList = explode(',', $config['sendType']);

		$result = array('code' => false, 'data' => array());
		foreach ($typeList as $type) {
			$result['data'][$type] = array('code' => false, 'data' => array());
			$data = &$result['data'][$type];

			$content = $this->getContent($msg, $type);
			switch ($type) {
				case 'email':
					// 获取用户列表,依次发送
					$where = array('userID' => array('in', $target));
					$users = Model('User')->where($where)->select();
					foreach ($users as $user) {
						$userID = $user['userID'];
						$name	= !empty($user['nickName']) ? $user['nickName'] : $user['name'];
						$value	= $user[$type];
						if (empty($value)) {
							$data['data']['error'][$name] = LNG('common.'.$type) . LNG('msgWarning.main.msgEmpty');
							continue;
						}
						// 检测邮箱地址
						if (!Input::check($value, $type)) {
							$data['data']['error'][$name] = "{$value} " . LNG('msgWarning.main.msgFmtErr');
							continue;
						}

						// 发送消息
						$user = array('name' => $name, $type => $value);
						$func = 'by' . ucfirst($type);
						$rest = $this->$func($user, $content);
						$name = $name.'|'.$value;	// 张三|zhangsan@163.com
						// 有一个发送成功,即为成功
						if ($rest['code']) {
							$data['code'] = true;
							$data['data']['success'][$name] = 1;
						} else {
							$data['data']['error'][$name] = $rest['data'] ? $rest['data'] : 0;
						}
					}
					break;
				case 'weChat':
				case 'dingTalk':
					$data = $this->byThird($target, $content, $type);
					break;
				default:break;
			}
		}
		// 有一类发送成功,即为成功
		foreach($result['data'] as $item) {
			if ($item['code']) {
				$result['code'] = true;
				break;
			}
		}
		return $result;
	}

	/**
	 * 通过第三方(钉钉、企业微信)发送通知
	 * @param [type] $user
	 * @param [type] $content	['','']
	 * @param [type] $type
	 * @return void
	 */
	public function byThird($user, $content, $type){
		$systemName = Model('SystemOption')->get('systemName');
		$title = "[{$systemName}]".LNG('msgWarning.main.ntcTitle');
		$content = array_merge(array('**'.$title.'**'), $content);
		$data = array(
			'msg'		=> array(
				'type'		=> 'markdown',	// text、markdown
				'title'		=> $title,		// 企业微信用不上
				'content'	=> implode("\n\n", $content)	// 一个\n无效
			),
			'target'	=> array(
				'user'	=> implode(',', $user)
			),
			'type'		=> $type
		);
		return Action('msgGatewayPlugin')->send($data);
		// $res = ActionCallHook('msgGatewayPlugin.send', $data);
	}

	/**
	 * 通过邮件发送通知
	 * @param [type] $user
	 * @param [type] $content	['','']
	 * @return void
	 */
	public function byEmail($user, $content){
        $systemName = Model('SystemOption')->get('systemName');
		$data = array(
			'type'			=> 'email',
			'input'			=> $user['email'],  // 邮箱地址
			'action'		=> 'email_msg_warning',
			'config'		=> array(
				'address'	=> $user['email'],
				'subject'	=> "[{$systemName}]".LNG('msgWarning.main.ntcTitle'),
				'content'	=> array(
					'type'  => 'notice', 
					'data'  => array(
						'user' => $user['name'],
						'text' => $content	// 数组
					)
				),
				'system'	=> array(	// 系统信息
					'icon'	=> STATIC_PATH.'images/icon/fav.png',
					'name'	=> $systemName,
					'desc'	=> Model('SystemOption')->get('systemDesc')
				),
			)
		);
		return Action('user.msg')->email($data);	// ->send()
    }

	/**
	 * 消息内容
	 * @param [type] $msg
	 * @param [type] $type
	 * @return void
	 */
	public function getContent($msg, $type){
		// 账号立即设置链接
		if ($type != 'email' && !empty($msg['user'])) {
			$msg['user'][count($msg['user'])-1] = '['.LNG('msgWarning.main.setNow').']('.APP_HOST.'#setting/user/account)';
		}
		// 获取消息列表
		$content = array();
		foreach ($msg as $key => $value) {
			if ($type == 'email' && !empty($content) && !empty($value)) {
				$content[] = '<hr style="border:none;border-top:1px solid #eee;">';
			}
			foreach ($value as $val) {
				// if ($type != 'email' && $key == 'raid') {
				// 	$val = '`'.$val.'`';
				// }
				$content[] = $val;
			}
		}
		return $content;
	}
}
ops.class.php
wget 'https://sme10.lists2.roe3.org/kodbox/plugins/msgWarning/controller/msg/ops.class.php'
View Content
<?php 
/**
 * 通知事件——运维管理类
 */
class msgWarningMsgOps extends Controller {
	public function __construct() {
		parent::__construct();
		$this->pluginName = 'msgWarningPlugin';
    }

	public function index($evntInfo) {
		$data = array();
		switch ($evntInfo['event']) {
			case 'opsUserAccErr':
				$data = $this->opsUserAccErr($evntInfo);
				break;
			default:
				# code...
				break;
		}
		return $data;
	}

	/**
	 * 账号安全风险,当前仅管理员未绑定邮箱,后续可扩展其他项
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function opsUserAccErr($evntInfo) {
		// $user = Session::get('kodUser');	// 计划任务没有登录,仅isRoot有效
		if (!KodUser::isRoot()) return array();

		// 判断是否绑定了有效邮箱
		$user = Model('User')->getInfoSimple(1);
		if (Input::check($user['email'], 'email')) return array();

		return array(LNG('msgWarning.ops.admEmlErr'));
	}

}
safe.class.php
wget 'https://sme10.lists2.roe3.org/kodbox/plugins/msgWarning/controller/msg/safe.class.php'
View Content
<?php 
/**
 * 通知事件——安全防护类
 */
class msgWarningMsgSafe extends Controller {
	public function __construct() {
		parent::__construct();
		$this->pluginName = 'msgWarningPlugin';
    }

	public function index($evntInfo) {
		return array();
	}

}
svr.class.php
wget 'https://sme10.lists2.roe3.org/kodbox/plugins/msgWarning/controller/msg/svr.class.php'
View Content
<?php 
/**
 * 通知事件——操作系统类
 */
class msgWarningMsgSvr extends Controller {
	public function __construct() {
		parent::__construct();
		$this->pluginName = 'msgWarningPlugin';
    }

	public function index($evntInfo) {
		$data = array();
		switch ($evntInfo['event']) {
			case 'svrDiskSizeErr':
				$data = $this->svrDiskSizeErr($evntInfo);
				break;
			case 'svrFileSysErr':
				$data = $this->svrFileSysErr($evntInfo);
				break;
			case 'svrCpuErr':
				$data = $this->svrCpuErr($evntInfo);
				break;
			case 'svrMemErr':
				$data = $this->svrMemErr($evntInfo);
				break;
			default:
				# code...
				break;
		}
		return $data;
	}

	/**
	 * 系统盘剩余空间不足
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function svrDiskSizeErr ($evntInfo) {
		$policy = $evntInfo['policy'];
		if (!$policy) return array();
		$sizeLimit = intval($policy['sizeMin']);
		if ($sizeLimit <= 0) return array();

		// 获取系统盘使用情况
		$info = $this->driverInfo(DATA_PATH);
		if (!$info) return array();

		$sizeFree = ($info['sizeMax'] - $info['sizeUse']);
		if ($sizeFree > 1024*1024*1024*$sizeLimit) return array();

		$size = size_format($sizeFree);
		$msg  = sprintf(LNG('msgWarning.svr.diskSizeErr'), $size);
		return array($msg);
	}
	// 根据路径获取磁盘使用情况
    private function driverInfo($path) {
		if(!file_exists($path)) return false;
		if(!function_exists('disk_total_space')){return false;}
		$sizeMax = @disk_total_space($path);
		return array(
			'sizeMax'	=> $sizeMax,
			'sizeUse'	=> $sizeMax - @disk_free_space($path),
		);
    }

	/**
	 * 文件系统异常
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function svrFileSysErr ($evntInfo) {
		// TODO cockpit中获取
		return array();
	}

	/**
	 * 文件系统异常
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function svrCpuErr ($evntInfo) {
		$policy = $evntInfo['policy'];
		if (!$policy) return array();
		$useRatio = $policy['useRatio'];
		$useTime  = intval($policy['useTime']);
		
		// 1.根据触发条件,判断是否需要发送信息
		$type = 'cpu';
		$data = false;
		$server = new ServerInfo();
		$usage = $server->cpuUsage();	// 0.23
		// pr($usage);exit;
		if($usage && $usage > floatval($useRatio / 100)) {
			$rest = $this->warnUsage(array('value' => $usage), $useTime, $type);
			if (!$rest) $data = $usage;
		}
		if (!$data) return array();

		// 2.拼接消息
		$msg = sprintf(LNG('msgWarning.svr.usageErr'), $useTime, 'CPU', $useRatio.'%', ($data*100).'%');
		return array($msg);
	}

	/**
	 * 文件系统异常
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function svrMemErr ($evntInfo) {
		// pr($evntInfo);exit;
		$policy = $evntInfo['policy'];
		if (!$policy) return array();
		$useRatio = $policy['useRatio'];
		$useTime  = intval($policy['useTime']);
		
		// 1.根据触发条件,判断是否需要发送信息
		$type = 'mem';
		$data = false;
		$server = new ServerInfo();
		$usage = $server->memUsage();	// [total=>1024,used=>24]
		// pr($usage);exit;
		$value = $usage['total'] > 0 ? round($usage['used']/$usage['total'], 3) : 0;
		if($value && $value > floatval($useRatio / 100)) {
			$rest = $this->warnUsage(array('value' => $value, 'data' => $usage), $useTime, $type);
			if (!$rest) $data = $value;
		}
		// pr($usage,$value,$data);exit;
		if (!$data) return array();

		// 2.拼接消息
		$msg = sprintf(LNG('msgWarning.svr.usageErr'), $useTime, LNG('msgWarning.main.memory'), $useRatio.'%', ($data*100).'%');
		return array($msg);
	}

	/**
	 * 记录cpu、内存异常信息
	 * @param [type] $data
	 * @param [type] $useTime	持续时长(分钟)
	 * @param [type] $type
	 * @return void true:不发送;false:发送
	 */
	private function warnUsage($data, $useTime, $type) {
		$model = Model('SystemWarn');
		$model->init($type);

		// 1.写入一条记录
		$insert = array(
			'value'		=> $data['value'],
			'content'	=> !empty($data['data']) ? $data['data'] : ''
		);
		$data = $model->add($insert);
		if (!$useTime || $useTime < 10) $useTime = 10; // 最小持续时长10分钟

		// 2.获取记录列表,删除指定时长之前的数据
		$list = $model->listData();
		$time = time() - 60 * $useTime;
		foreach($list as $k => $item) {
			$crtTime = intval($item['createTime']);
			if(!$useTime || $crtTime < $time) {
				$model->remove($item['id']);
				unset($list[$k]);
			}
		}

		// 3.判断是否符合发送提醒条件——持续的n分钟里,如20分钟,理论上有20条记录,只要达到80%(>=16条),就发送提醒
		$cnt = $useTime * 0.8;
		if(count($list) >= $cnt) {
			// 时间间隔需满足20分钟,避免每次都有数据写入时提前(16分钟)触发
			$max = reset($list);
			$min = end($list);
			$time = ceil(($max['createTime'] - $min['createTime'])/60);	// 持续记录数据时长(分钟)
			if ($time < $useTime) return true;

			// 每发送一次,删除此前的全部记录。持续时长=发送频率
			foreach($list as $k => $item) {
				$model->remove($item['id']);
			}
			return false;
		}
		return true;
	}


}

/**
 * mem、cpu记录
 */
class SystemWarnModel extends ModelBaseLight{
	public $optionType 	= '';
	public $modelType	= "SystemOption";
	public $field		= array('value','content'); //数据字段

	public function init($type){
		$this->optionType = 'System.'.$type.'WarnList';	// cpu、mem
	}
	//默认正序
	public function listData($id=false,$sort='modifyTime',$sortDesc=true){
		return parent::listData($id,$sort,$sortDesc);
	}
	public function remove($id){ 
		return parent::remove($id);
	}
	public function add($data){
		return parent::insert($data);
	}
}
sys.class.php
wget 'https://sme10.lists2.roe3.org/kodbox/plugins/msgWarning/controller/msg/sys.class.php'
View Content
<?php 
/**
 * 通知事件——系统服务类
 */
class msgWarningMsgSys extends Controller {
	public function __construct() {
		parent::__construct();
		$this->pluginName = 'msgWarningPlugin';
    }

	public function index($evntInfo) {
		$data = array();
		switch ($evntInfo['event']) {
			case 'sysStoreErr':
				$data = $this->sysStoreErr($evntInfo);
				break;
			case 'sysStoreBakErr':
				$data = $this->sysStoreBakErr($evntInfo);
				break;
			case 'sysStoreSizeErr':
				$data = $this->sysStoreSizeErr($evntInfo);
				break;
			case 'sysBakTaskErr':
				$data = $this->sysBakTaskErr($evntInfo);
				break;
			default:
				# code...
				break;
		}
		return $data;
	}

	/**
	 * 存储异常
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function sysStoreErr($evntInfo) {
		$data = Action($this->pluginName)->apiAct('sys', 'storage')->checkStoreList(true);
		// 过滤无系统数据的存储
        $data = array_filter($data, function ($item) {
            return $item['sysdata'] == 1;
        });
		if (!$data) return array();
		$cnt = count($data);
		// 写入日志
		$arr = array();
		foreach ($data as $item) {
			$arr[] = $item['name']."({$item['id']})";
		}
		write_log('【系统检测】'.$cnt.'个存储连接异常:'.implode('; ', $arr), 'storage');

		$msg = sprintf(LNG('msgWarning.sys.storeErr'), $cnt);
		return array($msg);
	}

	/**
	 * 备份存储异常
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function sysStoreBakErr($evntInfo) {
		// 获取备份存储
		$backup = Model('Backup')->config();
		if (!$backup || $backup['enable'] != '1') return array();
		$storeId = $backup['io'];

		// 获取异常存储列表
		// 此任务在sysStoreErr之后执行,直接获取缓存
		$data = Action($this->pluginName)->apiAct('sys', 'storage')->checkStoreList();
		if (!$data || !isset($data[$storeId])) return array();

		$msg = sprintf(LNG('msgWarning.sys.storeBakErr'), $data[$storeId]['name']);
		return array($msg);
	}

	/**
	 * 默认存储空间不足
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function sysStoreSizeErr($evntInfo) {
		$policy = $evntInfo['policy'];
		if (!$policy) return array();
		$sizeLimit = intval($policy['sizeMin']);
		if ($sizeLimit <= 0) return array();

		// 本地存储,获取所在磁盘的实际大小;其他获取配置大小
		$driver = KodIO::defaultDriver();
		if (strtolower($driver['driver']) == 'local') {
			$path = _get($driver, 'config.basePath', '');
			if (!$path) return array();
			$path = realpath($path);
			$data = $this->driverInfo($path);
            if(!$data) return array();
		} else {
			$sizeUse = Model('File')->where(array('ioType' => $driver['id']))->sum('size');
            $data = array(
                'sizeMax'   => floatval($driver['sizeMax']) * 1024 * 1024 * 1024,
                'sizeUse'   => floatval($sizeUse)
            );
		}

		$sizeFree = ($data['sizeMax'] - $data['sizeUse']);
		if ($sizeFree > 1024*1024*1024*$sizeLimit) return array();

		$size = size_format($sizeFree);
		$msg  = sprintf(LNG('msgWarning.sys.storeSizeErr'), $size);
		return array($msg);
	}
	// 根据路径获取磁盘使用情况
    private function driverInfo($path) {
		if(!file_exists($path)) return false;
		if(!function_exists('disk_total_space')){return false;}
		$sizeMax = @disk_total_space($path);
		return array(
			'sizeMax'	=> $sizeMax,
			'sizeUse'	=> $sizeMax - @disk_free_space($path),
		);
    }

	// 默认存储配置提醒(在系统盘)——不在此处获取,仅teamos
	public function sysStoreDefErr($evntInfo) {
		return array();
	}


	/**
	 * 备份任务异常
	 * @param [type] $evntInfo
	 * @return void
	 */
	public function sysBakTaskErr($evntInfo) {
		// 1.判断备份是否启用
		$backup = Model('Backup')->config();
		if (!$backup || $backup['enable'] != '1') return array();

		// 2.获取最近一条计划任务备份的记录
		$list = Model('Backup')->listData();
		$info = false;
		foreach ($list as $item) {
			if ($item['manual'] != '1') {
				$info = $item;
				break;
			}
		}
		if (!$info) return array();

		// 最近一条计划任务记录不是今天
		if ($info['name'] != date('Ymd')) return array();
		// TODO 不是今天且已过备份时间,也许应该提示——暂不处理

		// 3.判断备份是否成功
		// 3.1 备份中——应该根据Task任务判断是否异常中止(>2h没有更新),暂不处理
		if ($info['status'] == '0') return array();

		// 3.2 备份完成,判断是否成功——参考前端bakStatus
		$state = true;
		unset($info['result']['keep']);
		if ($info['content'] == 'sql') {
			unset($info['result']['file']);
		}
		foreach ($info['result'] as $key => $item) {
			if (!$item['status']) {
				$state = false;
				break;
			}
			// 数据库文件数不匹配
			if (in_array($key, array('db', 'dbFile')) && $item['total'] > $item['success']) {
				$state = false;
				break;
			}
			// // 文件未备份完成
			// if ($key == 'file' && $item['cntTotal'] != $item['cntSuccess']) {
			// 	$state = false;
			// 	break;
			// }
		}
		if ($state) return array();

		$msg = LNG('msgWarning.sys.bakTaskErr');
		return array($msg);
	}

}